Skip to content

You cannot start a load for a destroyed activity error #1097

Closed
@rsaphala

Description

@rsaphala

Glide Version: 3.7.0

Integration libraries: OkHttp3

Device/Android Version: All devices

Issue details / Repro steps / Use case background:
I have a fragment that contains a RecyclerView that loads Images using Glide. When the user scrolls really fast to the bottom and quits the app, the error occurs.

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

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof PostsViewHolder){
        HomeFeedPosts.data postsData = postsList.get(position);

        ((PostsViewHolder) holder).title.setText(postsData.user.username);

        Glide.with(((PostsViewHolder) holder).imagePost.getContext())
                .load(postsData.images.standard_resolution.url)
                .priority(Priority.IMMEDIATE)
                .placeholder(R.drawable.grey_placeholder)
                .into(((PostsViewHolder) holder).imagePost);

        Glide.with(((PostsViewHolder) holder).imageAvatar.getContext())
                .load(postsData.user.profile_picture)
                .priority(Priority.LOW)
                .into(((PostsViewHolder) holder).imageAvatar);


    } else if (holder instanceof ProgressBarViewHolder){
        ((ProgressBarViewHolder) holder).progressBar.setIndeterminate(true);
    }
}

Stack trace / LogCat:

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 com.saphala.gokilpedia_mobile.adapters.HomeFeedAdapter.onBindViewHolder(HomeFeedAdapter.java:86)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5465)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5498)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4735)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4611)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1988)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1384)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1347)
at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1174)
at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1031)
at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:4055)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
at android.view.Choreographer.doCallbacks(Choreographer.java:574)
at android.view.Choreographer.doFrame(Choreographer.java:543)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5113)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)                                                                                    
at dalvik.system.NativeStart.main(Native Method)

Activity

TWiStErRob

TWiStErRob commented on Mar 27, 2016

@TWiStErRob
Collaborator

Hmm, that's an interesting repro for this recurring issue. There's likely not a good way around it inside Glide, I suggest one of these workarounds (in descending order of quality):

  1. Pass in a Glide object: new HomeFeedAdapter(Glide.with(this))

    class HomeFeedAdapter extends Adapter {
        private final RequestManager glide;
        HomeFeedAdapter(RequestManager glide) {
            this.glide = glide;
        }
        @Override public void onBindViewHolder(ViewHolder holder, int position) {
            glide.load....
        }
    }

    This is a handy workaround, and it also makes your adapter flexible to use with fragment and activity as well; and the code cleaner: view.getContext() is usually a long way to access Glide.
    See http://stackoverflow.com/a/32887693/253468 why it's even an improvement.

  2. list.setAdapter(null) in onDestroy() or onStop(), which is incovenient to do all the time

  3. Check for ((Activity)view.getContext()).isDestroyed() or similar method, which may be unsafe and is even more inconvenient to do all the time

  4. Use Glide.with(context.getApplicationContext()), see http://stackoverflow.com/a/32887693/253468 why it may not be a good idea.

TWiStErRob

TWiStErRob commented on Mar 27, 2016

@TWiStErRob
Collaborator

Curious: How do you "quit the app" quick enough that the items are binding too late?

rsaphala

rsaphala commented on Mar 27, 2016

@rsaphala
Author

There's an OnScrollListener attached to the RecyclerView that loads more data from the server as you scroll to the bottom. To reproduce this issue simply scroll really fast and press the back button.

TWiStErRob

TWiStErRob commented on Mar 27, 2016

@TWiStErRob
Collaborator

Ah, I see, so your lazy loading delivers data to a dead activity, it's the same issue as the others: there was always a rogue async call involved.

rsaphala

rsaphala commented on Mar 27, 2016

@rsaphala
Author

I might be wrong on this, but doesn't the first option create a memory leak?

TWiStErRob

TWiStErRob commented on Mar 27, 2016

@TWiStErRob
Collaborator

I think at worst there's a reference cycle, which doesn't prevent GC from doing its job.

  • Activity references RecyclerView
  • Views reference Activity (getContext)
  • RecyclerView references Adapter
  • Adapter references RequestManager
  • RequestManager references Activity (not sure)
  • Activity references RequestManager through hidden RequestManagerFragment

RequestManager is aware of the activity/fragment lifecycle so any request will be cleared when they die, see linked SO. I don't think anything will be kept after destroy as the fragment is also destroyed.

rsaphala

rsaphala commented on Mar 27, 2016

@rsaphala
Author

Ahh ok thanks for clearing that up! The issue is now fixed.

kuldiep

kuldiep commented on Jul 20, 2016

@kuldiep

hii...m stuck with java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed

i have three activities in my app..so when i am starting 2nd activity there are some images which are loaded by glide in AsyncTask then i m going to further activity...again i came back to 2nd activity("no error") then i come back to 1st activity now again when i am going to 2nd activity app crashes with that exception...i tried glide.clearMemory()..but it dosent work :( please help me out

TWiStErRob

TWiStErRob commented on Jul 20, 2016

@TWiStErRob
Collaborator

@kuldiep I can only say the usual: make sure you don't start a load when the activity is destroyed or being destroyed. You can cancel the async task when the activity ia finishing (e.g. onStop). Please open a new issue with some code and more details, if you want more help.

kuldiep

kuldiep commented on Jul 20, 2016

@kuldiep

thanks for help....i think i come up with another solution and it works..i m just clearing glide.get(this).clearMemory in onResume, onRestart nd onDestroy methods..as of now i am not getting any error :)

TWiStErRob

TWiStErRob commented on Jul 20, 2016

@TWiStErRob
Collaborator

@kuldiep You might as well just disable memory cache altogether (similar applies to bitmap pools): use MemoryCacheAdapter as seen in wiki; and remember, this is a not a solution you found, but a hack hiding the real problem.

kuldiep

kuldiep commented on Jul 20, 2016

@kuldiep

ya my approach is not a solution but i'll keep your approach of stopping async task in onStop method for letter use..thanks

9 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @TWiStErRob@boylenssen@tangyiwu@rsaphala@kuldiep

        Issue actions

          You cannot start a load for a destroyed activity error · Issue #1097 · bumptech/glide