when is it safe to call clear(Target)
- 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
Assessment
This issue has not been assessed yet.