【问题标题】:Coulden't Toast message in onPostExecute in asyncTask无法在 asyncTask 中的 onPostExecute 中发送消息
【发布时间】: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 不会变得太多 :) 希望它有所帮助!

标签: android kotlin android-asynctask


【解决方案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()
          

          【讨论】:

            猜你喜欢
            • 2016-10-28
            • 1970-01-01
            • 1970-01-01
            • 2015-05-08
            • 2022-06-15
            • 2011-11-13
            • 2021-12-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多