Java RecyclerView中的AsyncTask抛出您无法在回调时为已销毁的活动启动加载
我有一个RecyclerView适配器,每隔几秒钟就会更新一次。每次调用AsyncTask时,它将从服务器检索数据,然后调用适配器内的以下方法:Java RecyclerView中的AsyncTask抛出您无法在回调时为已销毁的活动启动加载,java,android,android-asynctask,android-recyclerview,android-glide,Java,Android,Android Asynctask,Android Recyclerview,Android Glide,我有一个RecyclerView适配器,每隔几秒钟就会更新一次。每次调用AsyncTask时,它将从服务器检索数据,然后调用适配器内的以下方法: public static void updateItem(final FavoritesViewHolder holder, DBHelper dbHelper, int position, Channel channel, Context context, boolean success) { Glide.with(cont
public static void updateItem(final FavoritesViewHolder holder, DBHelper dbHelper, int position, Channel channel, Context context, boolean success) {
Glide.with(context).load(channel.getAvatar())
.error(R.drawable.youtube_default_avatar)
.placeholder(R.drawable.youtube_default_avatar)
.into(holder.channelAvatarView);
dbHelper.updateFavorites(channels.get(position));
Glide.get(context).clearMemory();
}
(我删除了几行,它们对这个问题没有影响)
但是,如果用户快速关闭应用程序或转到另一个应用程序,并且AsyncTask刚刚调用了该方法(是的,AsyncTask正在被取消,不用担心,它会成功完成并调用该方法),Glide会抛出以下错误:
java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed(RequestManagerRetriever.java:134)
at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:102)
at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:87)
at com.bumptech.glide.Glide.with(Glide.java:629)
at it.bjarn.xxx.xxx.adapters.FavoritesAdapter.updateItem(FavoritesAdapter.java:204)
at it.bjarn.xxx.xxx.tasks.FavoriteUpdateTask.onPostExecute(FavoriteUpdateTask.java:104)
at it.bjarn.xxx.xxx.tasks.FavoriteUpdateTask.onPostExecute(FavoriteUpdateTask.java:27)
at android.os.AsyncTask.finish(AsyncTask.java:667)
at android.os.AsyncTask.-wrap1(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:684)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
这是我的AsyncTask的onPostExecute():
protected void onPostExecute(AsyncTaskResult<Channel> result) {
if (result.getError() != null) {
Log.e("FavoritesUpdateTask", "Exception while retrieving results: " + result.getError().toString());
Glide.get(mContext).clearMemory();
} else if (isCancelled()) {
Log.d("FavoritesUpdateTask", "Cancelled");
Glide.get(mContext).clearMemory();
} else {
Log.d("FavoritesUpdateTask", "Succesfully returned channel object");
FavoritesAdapter.updateItem(mHolder, mDbHelper, mPosition, result.getResult(), mContext, true);
}
}
我想。。问题就在这里
Glide.with(context).
因为,这里的活动被销毁了,它仍然在使用销毁活动的上下文。我想。。问题就在这里
Glide.with(context).
因为,这里的活动已被销毁,它仍在使用已销毁活动的上下文。发生崩溃是因为在调用Glide时,您的活动/上下文已被销毁。我猜您是在一个具有攻击性GC的设备上,或者您在“开发人员选项”中启用了“不要将活动保留在后台” 为了防止崩溃,我想添加一个空检查就足够了:
if(context != null && (!(Activity)context).isFinishing()) {
updateItem()
}
我不确定Glide对上下文的引用是弱还是强。这可能会导致内存泄漏。理想情况下,销毁活动时应该取消异步任务。如果您不能采用这种方法,您应该重新考虑您的设计。崩溃正在发生,因为调用Glide时您的活动/上下文已被破坏。我猜您是在一个具有攻击性GC的设备上,或者您在“开发人员选项”中启用了“不要将活动保留在后台” 为了防止崩溃,我想添加一个空检查就足够了:
if(context != null && (!(Activity)context).isFinishing()) {
updateItem()
}
我不确定Glide对上下文的引用是弱还是强。这可能会导致内存泄漏。理想情况下,销毁活动时应该取消异步任务。如果您不能采用这种方法,您应该重新考虑您的设计。如果AsyncTask在移出活动时被取消,updateItem()方法是如何执行的?不,AsyncTask已经完成,因此它会在成功时调用updateItem()方法。但如果用户随后关闭应用程序或转到其他活动,则会崩溃。这是一个很严重的瞬间发生的事情。但是,如果该方法在尚未完成时被取消,它仍然会取消任务,并且不会像预期的那样调用updateItem()。您将“完成”异步任务与“取消”混为一谈。您是在onPause或onStop中调用AsyncTask的cancel()方法吗?我无法从活动中取消它,因此我尝试这样做:请参阅post中的edit它似乎不起作用,因为我在取消时设置的logcat中没有看到“Cancelled”消息。如果AsyncTask在移出活动时被取消,那么updateItem()如何操作方法正在执行?不看,AsyncTask已完成,因此它在成功时调用updateItem()方法。但如果用户随后关闭应用程序或转到其他活动,则会崩溃。这是一个很严重的瞬间发生的事情。但是,如果该方法在尚未完成时被取消,它仍然会取消任务,并且不会像预期的那样调用updateItem()。您将“完成”异步任务与“取消”混为一谈。您是在onPause或onStop中对AsyncTask调用cancel()方法吗?我无法从活动中取消它,因此我尝试执行以下操作:请参阅在post中编辑它似乎不起作用,因为我在取消时设置的logcat中没有看到“已取消”消息。谢谢您的建议,我已经使用了这种方法,希望我的用户能够解决这个问题。我似乎无法复制此问题,但我的测试版用户可以。更新:遗憾的是,这并没有解决我的问题,似乎有点复杂。您能否确认是否可以通过在“开发人员选项”中启用“不要将活动保留在后台”来复制此问题?谢谢您的建议,我已经使用了这种方法,希望我的用户能够解决这个问题。我似乎无法复制此问题,但我的测试版用户可以。更新:遗憾的是,这并没有解决我的问题,似乎有点复杂。您能否确认是否可以通过在“开发人员选项”中启用“不要将活动保留在后台”来复制此问题?