Glide: You cannot start a load for a destroyed activity

Created on 11 Apr 2016  Â·  9Comments  Â·  Source: bumptech/glide

Glide Version:compile 'com.github.bumptech.glide:glide:3.7.0'

Integration libraries:No

Device/Android Version:4.2.1,4.2.2,5.1

Issue details / Repro steps / Use case background: random crash(93 times in 12797 sessions) in my application which was due to Glide image loading,even did check for activity finish.

Glide load line / GlideModule (if any) / list Adapter code (if any):

private void setImageWithGlide(Context context, byte[] data) {
    if (context == null || ((Activity) context).isFinishing())
        return;

    if (riv == null) {
        riv = getRiv();
    }

    Glide.with(context).load(data).asBitmap().
            listener(new RequestListener<byte[], Bitmap>() {
                @Override
                public boolean onException(Exception e, byte[] model, Target<Bitmap> target, boolean isFirstResource) {
                    return false;
                }

                @Override
                public boolean onResourceReady(Bitmap resource, byte[] model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
                    riv.setImageBitmap(resource);
                    fab.setImageDrawable(riv.getDrawable());
                    return true;
                }
            }).override(Constants.pxToDp(56), Constants.pxToDp(56)).
            into(riv);
}

Layout XML:
Not relevant

Stack trace / LogCat:

IllegalArgumentException (@ContextMenuActivity:a:-1) {Crash Report Thread:main Exception:
java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
    at com.bumptech.glide.d.l.a(Unknown Source)
    at com.bumptech.glide.d.l.a(Unknown Source)
    at com.bumptech.glide.g.b(Unknown Source)
    at ...
question

All 9 comments

Based on the description of onDestroy in the table below the image and lifecycle method listing:

onDestroy: The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.

isFinishing() == false does not mean that the activity is alive, because it'll return false for temporary destroys (e.g. rotation). Since Glide throws this exception when isDestroyed is true, you should be using the same to protect against latecoming callbacks. The best is if you can cancel the async task (in the opposite lifecycle method of where it was .execute()d) and check isCancelled() in onPostExecute, and don't do anything if it was cancelled.

Alternatively use the hacky workaround of caching Glide.with(context) into a variable earlier, so when you receive the byte[] data from the background into the UI you don't need to do with -> no exception.

@TWiStErRob Thanks to reply,
you mean to add
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()) this also

i.e. Do I need to check as

if (context == null || ((Activity) context).isFinishing() || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()))

Yes, add that, and you can remove isFinishing as it doesn't give you the info you want.

But the key would be the cancelling of the task and checking is cancelled, the isDestroyed may not even be necessary.

Thanks Again,But In my case I cannot cancel AsyncTask.

Just curious: How come you can't cancel?

As I want to complete my Asynctask which is created for building cache for application start.

How to check if a Fragment was destroyed till this moment?

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static boolean isActivityDestroyed(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1
&& activity != null && activity.isDestroyed()) {
return true;
}
return false;
}

when you load image in Activity, please check like this. If the activity isDestroyed, stop load image by Glide, else load image by Glide

@Gaket
when you load image in a fragment , please get the Activity first like this, and then check whether the activity has destroyed

private static Activity getActivity(Context context) {
if (context == null) {
return null;
}
if (context instanceof Activity) {
return (Activity) context;
} else if (context instanceof ContextWrapper) {
return getActivity(((ContextWrapper) context).getBaseContext());
}
return null;
}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Ncit picture Ncit  Â·  3Comments

PatrickMA picture PatrickMA  Â·  3Comments

Anton111111 picture Anton111111  Â·  3Comments

sant527 picture sant527  Â·  3Comments

AndroidJohnsonWang picture AndroidJohnsonWang  Â·  3Comments