我有一个RecyclerView适配器,每隔几秒就会更新一次。每次调用AsyncTask时,它会从服务器检索数据,然后调用适配器内的以下方法:
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);
}
}
//编辑:
我也尝试从适配器中取消任务,因为我无法从Activity本身取消它(FavoritesUpdateTask在适配器内部,也就是在onBindViewHolder()中调用的地方):
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
if (favoriteUpdateTask != null) {
favoriteUpdateTask.cancel(true);
}
}
答案 0 :(得分:0)
我认为..这就是问题所在。
Glide.with(context).
Cuz,这里的活动被破坏了,它仍在使用被破坏活动的上下文。
答案 1 :(得分:0)
崩溃正在发生,因为您的活动/上下文在调用Glide时被销毁。我猜你是在装有侵略性GC的设备上,或者你在“开发者选项”中启用了“不要在后台保持活动”。
为了防止崩溃,我想添加空检查就足够了:
if(context != null && (!(Activity)context).isFinishing()) {
updateItem()
}
我不确定格莱德是否对上下文有弱或强的引用。这可能会导致内存泄漏。理想情况下,您应该在销毁活动时取消AsyncTask。如果你不采取这种方法,你应该重新考虑你的设计。