bumptech / bumptech/glide

when is it safe to call clear(Target)

Open
#4,341 2 comments 0 reactions 0 assignees View on GitHub
stale
Dominant language
Java
Stars
35k
Forks
6.2k
Avg merge
1d 11h
Merged PRs (30d)
8

Description

Having an activity which has a few fragments in the backstack.
Every fragment loads some view (the ViewItem), in the ViewItem it has a ImageView, and uses CustomTarget for loading the image from remote. It's been working but noticed the a lot of bitmap are held in the memory after the host activity has been closed.

So trying to call **Glide.with(imageView!!.context).clear(myThumbnailTarget)** at the fragment's onDestroy() path.
It works when pop fragment from the backstack which calls the popped fragment's onDestroy().
But when popping the last fragment the hosting activity is also finishing, and the clear(Target) crashes.

question, when is the proper time to clear the target?

```
class ViewItem: ConstraintLayout() {
val imageView = // get from layout

private var myImageTarget: MyImageTarget? = null
private class MyImageTarget(var hostRef: WeakReference?, thumbnail: ImageView) : CustomViewTarget(thumbnail) {
fun clear() {
hostRef = null
}

override fun onLoadFailed(errorDrawable: Drawable?) {
getView().visibility = View.GONE
hostRef?.get()?.playButton?.visibility = View.GONE
}

override fun onResourceReady(
resource: Drawable,
transition: Transition?
) {
var viewItem = hostRef?.get()
if (viewItem != null) {
getView().visibility = View.VISIBLE
getView().setImageDrawable(resource)
if (viewItem.contentType == ArticleType.VIDEO) {
viewItem.playButton?.visibility = View.VISIBLE
} else {
viewItem.playButton?.visibility = View.GONE
}
}
}

override fun onResourceCleared(placeholder: Drawable?) {
var viewItem = hostRef?.get()
if (viewItem != null) {
getView().visibility = View.GONE
viewItem.playButton?.visibility = View.GONE
}
}
}

fun bindView() {

myImageTarget = MyImageTarget(WeakReference(this), imageView)
imageView.loadImg(
imageUrl = theUrl,
target = myImageTarget
)
}

fun onDestroy() {
if (imageView != null && myImageTarget != null) {
Glide.with(imageView!!.context).clear(myImageTarget) //<== crash 'You cannot start a load for a destroyed activity"
}
myImageTarget = null
}
}

internal fun ImageView.loadImg(
imageUrl: String,
diskCacheStrategy: DiskCacheStrategy = DiskCacheStrategy.AUTOMATIC,
skipMemoryCache: Boolean = true,
roundingRadius: Int = 0,
target: Target? = null,
requestOptions: RequestOptions = RequestOptions(),
decodeFormat: DecodeFormat = DecodeFormat.PREFER_RGB_565
) {
requestOptions
.diskCacheStrategy(diskCacheStrategy)
.format(decodeFormat)

if (roundingRadius > 0) {
requestOptions.transform(CenterCrop(), RoundedCorners(roundingRadius))
}

if (imageUrl.isNotBlank()) {
val r= Glide.with(this.context)
.load(imageUrl)
.apply(requestOptions)
.skipMemoryCache(skipMemoryCache)

if (target == null) {
r.into(this)
}else {
r.into(target)
}
}
}
```

the crash call stack:
```
Caused by: java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed(RequestManagerRetriever.java:317)
at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:128)
at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:108)
at com.bumptech.glide.Glide.with(Glide.java:776)
at com.viewItem.onDestroy(ViewItem.kt:74)
at com.fragment.ContentFragment.onDestroy(ContentFragment.kt:316)
at androidx.fragment.app.Fragment.performDestroy(Fragment.java:2928)
at androidx.fragment.app.FragmentStateManager.destroy(FragmentStateManager.java:492)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1308)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1368)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1446)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1509)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2637)
at androidx.fragment.app.FragmentManager.dispatchDestroy(FragmentManager.java:2621)
at androidx.fragment.app.FragmentController.dispatchDestroy(FragmentController.java:330)
at androidx.fragment.app.FragmentActivity.onDestroy(FragmentActivity.java:365)
at androidx.appcompat.app.AppCompatActivity.onDestroy(AppCompatActivity.java:233)
at android.app.Activity.performDestroy(Activity.java:6881)
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.