You cannot start a load for a destroyed activity in relativelayout image using glide

AndroidAndroid Glide

Android Problem Overview


I am using relativelayout to set an image.Why I hadn't using imageview means, inside relativelayout image, I am setting icons.

I dont know what is the issue exactly in glide.I have posted the stacktrace and relevant code below:

Logcat:

 FATAL EXCEPTION: main
   Process: com.app.steve, PID: 15928 
 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.Glide.with(Glide.java:644)
                                                                    at com.app.steve.TabMorePagesDetailActivity$allPageDetails.onPostExecute(TabMorePagesDetailActivity.java:1050)
     at com.app.steve.TabMorePagesDetailActivity$allPageDetails.onPostExecute(TabMorePagesDetailActivity.java:885)
    at android.os.AsyncTask.finish(AsyncTask.java:632)
    at android.os.AsyncTask.access$600(AsyncTask.java:177)
   at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5221)
   at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

TabMorePagesDetailActivity.java:

RelativeLayout rlPageCoverImg;

rlPageCoverImg = (RelativeLayout)findViewById(R.id.rl_club_cover_img);

@Override
		protected void onPostExecute(String response) {
			super.onPostExecute(response);
			
			dialog.dismiss();
        ............

  	String coverIMGurl = cover_avatar_obj.getString("url");

	Log.e("ImgURL", coverIMGurl);

 Glide.with(TabMorePagesDetailActivity.this).load(coverIMGurl).asBitmap().signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
										.into(new SimpleTarget<Bitmap>(500, 500) {

	@Override
	public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
	Drawable drawable = new BitmapDrawable(getResources(), resource);
	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
											rlPageCoverImg.setBackground(drawable);
	}
	}
	});

	}else {

	rlPageCoverImg.setBackgroundResource(R.drawable.bg_golive);

	}
 


	@Override
 protected void onDestroy()
 {
	super.onDestroy();
	Glide.clear(rlPageCoverImg);

 }

layout.xml:

 <RelativeLayout
            android:id="@+id/rl_club_cover_img"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="@drawable/cancel_image" >

  // Inside this relativelayout image, I'm using buttons and icons


 </RelativeLayout>

Android Solutions


Solution 1 - Android

Use:

Glide.with(getApplicationContext()).load(...)

Instead of:

Glide.with(TabMorePagesDetailActivity.this).load(...)

Hope it will solve your problem~

BEWARE: See https://stackoverflow.com/questions/31964737/glide-image-loading-with-application-context/32887693#32887693 if you decide to use applicationContext

Solution 2 - Android

You can simply check the context is destroyed or not manually as;

if (context == null) {
    return
} else if (context !is Application) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        if (context is FragmentActivity) {
            if ((context as FragmentActivity).isDestroyed) {
                return
            }
        } else if (context is Activity) {
            if ((context as Activity).isDestroyed) {
                return
            }
        }
    }
}

This can also be represented as a Kotlin extension function:

/**
 * Return true if this [Context] is available.
 * Availability is defined as the following:
 * + [Context] is not null
 * + [Context] is not destroyed (tested with [FragmentActivity.isDestroyed] or [Activity.isDestroyed])
 */
fun Context?.isAvailable(): Boolean {
    if (this == null) {
        return false
    } else if (this !is Application) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            if (this is FragmentActivity) {
                return !this.isDestroyed
            } else if (this is Activity) {
                return !this.isDestroyed
            }
        }
    }
    return true
}

Solution 3 - Android

Inspired from a GitHub thread, I am using this before loading any image

final Context  context = getApplication().getApplicationContext();

if (isValidContextForGlide(context)){
                // Load image via Glide lib using context
               
  }

 public static boolean isValidContextForGlide(final Context context) {
    if (context == null) {
        return false;
    }
    if (context instanceof Activity) {
        final Activity activity = (Activity) context;
        if (activity.isDestroyed() || activity.isFinishing()) {
            return false;
        }
    }
    return true;
}

Solution 4 - Android

Please do not use Glide.with(getApplicationContext()) unless you really need to, for reasons discussed here: https://stackoverflow.com/questions/31964737/glide-image-loading-with-application-context/32887693#32887693

The correct answer is outlined here: https://github.com/bumptech/glide/issues/1484#issuecomment-365625087

In Kotlin, that can be written as an extension function:

fun Context.isValidGlideContext() = this !is Activity || (!this.isDestroyed && !this.isFinishing)

Solution 5 - Android

I have got the same issue before few days.I have solved this to passing the Application context memory behalf of current Class context memory.

May be it will help you :-

use this code

 Glide.with(getApplicationContext())
           .load(coverIMGurl)
           .asBitmap()
           .signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
                                    .into(new SimpleTarget<Bitmap>(500, 500) {....}

Even you are getting this issue then read this article carefully "https://github.com/bumptech/glide/issues/1097"

overview for this issue : This is an issue of Glide library.

Solution 6 - Android

Try this before load your image with Glide, in my case mirefer is a StorageReference, miimagen is a ImageView. I solved this problem, with this. I hope it could help you.

if (!this.isFinishing ()) {
                // Load the image using Glide
                Glide.with(YourActivity.this)
                        .using(new FirebaseImageLoader())
                        .load(mirefer)
                        .into(miimagen);
            }

Solution 7 - Android

Setup Glide with a parameter which has the correct lifecycle. For example: use Glide.with(this) instead of Glide.with(getContext()) in a custom view.

Solution 8 - Android

Here is a Kotlin extension that puts together a few answers above - this, this, and this:

/**
 * Returns true when [Context] is unavailable or is about to become unavailable
 */
fun Context?.isDoomed(): Boolean = when (this) {
    null -> true
    is Application -> false
    is Activity -> (this.isDestroyed or this.isFinishing)
    else -> false
}

Solution 9 - Android

Don't just use context in adapter which you take from activity as context=this rather use context.getApplicationContext();

Solution 10 - Android

the other way is to check if the activity is destroyed or not, then load into UI element.

if (!newActivty.isDestroyed()){
   ...
}

Solution 11 - Android

hi in view model for frament The activity context is kept even when you press the back button and exit the program. And go back to the program, you do not need to re-value the context because the context is static

@Override
    public void onBindViewHolder(@NonNull final viewholder viewholder, final int i) {
        final Model_Post model_post = list.get(i);
        Log.e(TAG, "onBindViewHolder: "+model_post.getImageurl());

        Glide.with(MainActivity.activity)
                .load(Uri.parse(model_post.getImageurl()))
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(viewholder.itemsPostBinding.imgvItempost);

    }

You must do this in main activity :

public static AppCompatActivity activity;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    activity = MainActivity.this;
}

Solution 12 - Android

Pls use Glide.with(holder.itemView.getContext()).load....... It has solved my issue ref https://github.com/bumptech/glide/issues/2690

Solution 13 - Android

Just use this helper class:

/**
 * @Lukas Niessen
 */
public class GlideUsus {

    public static final String TAG = "GlideUsus";

    public interface Interface {
        void doIfValidContext(RequestManager requestManager);
    }

    public static void execute(Context context, GlideUsus.Interface action) {
        if (isValidContextForGlide(context)) {
            action.doIfValidContext(Glide.with(context));
        } else {
            // nothing
            Log.v(TAG, "Loading image failed");
        }
    }

    public static boolean isValidContextForGlide(final Context context) {
        if (context == null) {
            return false;
        }
        if (context instanceof Activity) {
            final Activity activity = (Activity) context;
            if (activity.isDestroyed() || activity.isFinishing()) {
                return false;
            }
        }
        return true;
    }
}

Usage:

GlideUsus.execute(mContext, (a -> a.load(uri).into(image)));

Solution 14 - Android

In activity I use Glide.with(getApplicatonContext()) and in adapter I use Glide.with(myContext.getApplicatonContext())

//It works for me fine.

//for adapter

Context myContext;

//also initilize in `oncreateViewHolder`

@Override
    public MessagesHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_messages_layout, parent, false);
        myContext = parent.getContext();
        return new MessagesHolder(view);
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteveView Question on Stackoverflow
Solution 1 - AndroidFerdous AhamedView Answer on Stackoverflow
Solution 2 - AndroidDiRiNoiDView Answer on Stackoverflow
Solution 3 - AndroidSethuraman SrinivasanView Answer on Stackoverflow
Solution 4 - AndroidLukeView Answer on Stackoverflow
Solution 5 - AndroidPeterView Answer on Stackoverflow
Solution 6 - AndroidLiliana JView Answer on Stackoverflow
Solution 7 - AndroidCristanView Answer on Stackoverflow
Solution 8 - AndroidGuidoView Answer on Stackoverflow
Solution 9 - AndroidSamuel Aktar LaskarView Answer on Stackoverflow
Solution 10 - AndroidGv RaviView Answer on Stackoverflow
Solution 11 - Androidali moradiView Answer on Stackoverflow
Solution 12 - AndroidBineesh KumarView Answer on Stackoverflow
Solution 13 - AndroidLukas NiessenView Answer on Stackoverflow
Solution 14 - AndroidSheraz Hussain TuriView Answer on Stackoverflow