You cannot start a load for a destroyed activity in relativelayout image using glide
AndroidAndroid GlideAndroid 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);
}