无法在 asyncTask 中的 onPostExecute 中发送消息
Posted
技术标签:
【中文标题】无法在 asyncTask 中的 onPostExecute 中发送消息【英文标题】:Coulden't Toast message in onPostExecute in asyncTask 【发布时间】:2020-06-05 16:44:18 【问题描述】:我的应用程序在Toast
OnPostExecute
上崩溃。
我试图将 context
的 MainActivity()
设置为 Toast 中的上下文,但它抛出了相同的异常
例外是
java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“android.content.res.Resources android.content.Context.getResources()”
发生了什么?我该如何解决?
我是从另一个onPostExecute
的AsyncTask
调用这个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@MainActivity 或 applicationContext。
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 进程