无法在 asyncTask 中的 onPostExecute 中发送消息

Posted

技术标签:

【中文标题】无法在 asyncTask 中的 onPostExecute 中发送消息【英文标题】:Coulden't Toast message in onPostExecute in asyncTask 【发布时间】:2020-06-05 16:44:18 【问题描述】:

我的应用程序在ToastOnPostExecute 上崩溃。

我试图将 contextMainActivity() 设置为 Toast 中的上下文,但它抛出了相同的异常

例外是

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“android.content.res.Resources android.content.Context.getResources()”

发生了什么?我该如何解决?

我是从另一个onPostExecuteAsyncTask 调用这个AsyncTask 的另一个AsyncTask

 InsertInDateDb( MainActivity(), dateEntity).execute()

AsyncTask 在MainActivity

private class InsertInDateDb(var context: MainActivity, var dateEntity: DateEntity) :
    AsyncTask<Void, Void, Boolean>() 
    override fun doInBackground(vararg p0: Void?): Boolean 
        val dateRoomDatabase: DateRoomDatabase = DateRoomDatabase.getDateDb(context)!!

        val dateEntity1 = dateEntity
        dateRoomDatabase!!.getDateDao().insertDate(dateEntity)
        return true
    

    override fun onPostExecute(result: Boolean?) 
        if (result!!) 

            try 
                Toast.makeText(
                   MainActivity(),
                    "Entry added to date database",
                    Toast.LENGTH_LONG
                ).show()
             catch (e: Exception) 
                Log.d("tag", "Exception $e")
            


        
    

【问题讨论】:

你在哪里以及如何传递上下文/MainActivity?也许有一个错误。我还将上下文从 context: MainActivity 更改为 context: Context。 @Colibri 你是对的。我在调用 asyncTask 时将 MainActivity() 作为上下文传递 但是传递 'this' 不起作用,因为我是从另一个 asyncTask 的 onPostExecute 调用它。我该如何解决? 我现在已经添加了我的 cmets 作为答案,所以这里的 cmets 不会变得太多 :) 希望它有所帮助! 【参考方案1】:

MainActivity() 为您提供 MainActivity新实例,它不是 当前正在运行的实例强>MainActivity。

您应该改用 this@MainActivityapplicationContext

1. Toast.makeText(this@MainActivity, "Entry added to date database", Toast.LENGTH_LONG).show()

2. Toast.makeText(applicationContext, "Entry added to date database", Toast.LENGTH_LONG).show()

【讨论】:

@Makarand 请只使用 Toast.makeText(this@MainActivity, "Entry added to date database", Toast.LENGTH_LONG).show()【参考方案2】:

将 MainActivity() 替换为上下文

Toast.makeText(context, "Entry added to date database", Toast.LENGTH_LONG).show()

【讨论】:

【参考方案3】:

错误似乎在于将上下文传递给 InsertInDateDb 实例。

如果此任务嵌入到另一个任务中,则意味着您需要更快地传递上下文(通过传递“this”)或按照 Maurici Guell Hernandez 的回答中的建议,使用接口,传递类似于“OnFinishedListener”的内容到您的 AsyncTasks。

您将在开始时创建 OnFinishedListener(例如在 MainActivity 中),并使用“onFinished”方法在其中您可以 Toast。 然后将Listener分别传递给AsyncTasks,最后调用postExecute中的“onFinished”方法,运行它/让它显示Toast :)

请记住,上下文必须是实际运行的活动(“this”)的实例,而不是尚未创建的东西。

【讨论】:

【参考方案4】:

我强烈建议使用观察者模式从 AsyncTask 向活动发送信息。

简单、安全、优雅。这是一个示例。

class WriteToDiskAsync(private val writeToDiskListener: WriteToDiskListener) : AsyncTask<Void, Void, File?>() 

    override fun doInBackground(vararg params: Void?): File? 
        //whatever
    

    override fun onPostExecute(survey: File?) 
        writeToDiskListener.writeToDiskFinished()
    

界面如下:

interface WriteToDiskListener 

    fun writeToDiskFinished()

以及活动或片段:

class MainActivity : AppCompatActivity(), WriteToDiskListener 
    //Your stuff...

    override fun writeToDiskFinished() 
        if (!isFinishing) 
            Toast.makeText(this@MainActivity, "Entry added to date database", Toast.LENGTH_LONG).show()
        
    

建议使用“!isFinishing”检查以避免某些时刻出现异常。

要从 MainActivity 调用 AsyncTask,您只需这样做:

WriteToDiskAsync(this).execute()

希望对你有帮助。

毛里西奥

【讨论】:

好的,但是在调用AsyncTask时我应该如何传递实现接口的引用? 我已经通过'MainActivity()'作为接口的参考,但它仍然崩溃 我用您要求的信息编辑了我的答案 我无法通过“this”作为接口参考。 bcz 它在另一个 AysncTask 的 onPostExecute 中,因此它指向该类而不是 MainActivity。【参考方案5】:

在 asysnTask 中使用 mainActivityContext 作为上下文;

var mainActivityContext= null
 override fun onCreate(savedInstanceState: Bundle?) 
mainActivityContext=this
...
..
.

【讨论】:

【参考方案6】:

像这样打电话给你的AsynckTask

    InsertInDateDb(this@MainActivity, dateEntity).execute()

然后像这样在onPostExecute() 敬酒

 Toast.makeText(
            context,
            "Entry added to date database",
            Toast.LENGTH_LONG
        ).show()

【讨论】:

【参考方案7】:

创建您的 Activity 对象,如下所示

 lateinit var mActivity: Activity

现在将您的活动设置为您的活动对象。

mActivity = this@YourActivity

在 Toast 中使用 mActivity

Toast.makeText(mActivity, "Entry added to date database", Toast.LENGTH_LONG).show()

【讨论】:

以上是关于无法在 asyncTask 中的 onPostExecute 中发送消息的主要内容,如果未能解决你的问题,请参考以下文章

无法覆盖 AsyncTask 类中的 onPostExecute() 方法或使其触发

无法在 asyncTask 中的 onPostExecute 中发送消息

即使使用取消方法也无法取消 AsyncTask 中的 doInBackground 进程

无法将值传递给Android中的AsyncTask

在 AsyncTask 的 onPostExecute 之后,无法按意图更新 RecyclerView

无法在Asynctask Android,java中调用View