Reputation: 2599
I am writing an Android app which makes extensive use of ViewPagers that contain high-res images. I am extending PagerAdapter and manually creating and destroying items when appropriate. It works fine until this fragment gets placed on that backstack. I would like to remove all images from memory when the fragment with ViewPagers gets placed on the backstack, but I can't figure out a way.
I tried removing all the backing data from the list that the adapter uses, then call .notifyDataSetChanged(), but this doesn't go through and call PagerAdapter.destroyItem() for each page like I hope.
I also tried using FragmentStatePagerAdapter, but this also didn't seem to clear out any memory during app usage.
How can I force a PagerAdapter to call destroyItem() on all items in a pager?
Here is my code for the View that contains the ViewPager:
class ContentStrip : LinearLayout {
var title : WeakReference<TextView>? = null
var titleString: String = ""
lateinit var pager : WeakReference<MyViewPager>
var data:ContentCollection? = null
//[...] other view methods
//Called from parent fragment's onDestroy
fun clearMemory() {
if (data == null) return
var i = -1
var contentItem : ContentItem
for(item in data!!.contentItems) {
i++
var v:View? = pager.get().findViewWithTag("${titleString}$i") ?: continue
contentItem = v as ContentItem
contentItem.image?.setImageDrawable(null)
contentItem.image = null
removeView(contentItem)
}
title = null
pager.get().removeAllViews()
data?.contentItems?.clear()
pager.get().adapter.notifyDataSetChanged()
invalidate()
}
class ContentStripAdapter() : PagerAdapter() {
lateinit var outer: WeakReference<ContentStrip>
fun setOuterRef(cs:ContentStrip) : ContentStripAdapter {
outer = WeakReference(cs)
return this
}
//[...]other PagerAdapter methods
override fun destroyItem (container:ViewGroup, position:Int, obj:Any) {
var img : ContentItem? = obj as ContentItem
img?.image?.setImageDrawable(null)
img?.image = null
img?.title = null
container.removeView(img)
img = null
}
override fun getCount(): Int {
return outer.get().data?.contentItems?.count()!!
}
}
}
Upvotes: 1
Views: 2794
Reputation: 54705
PagerAdapter.destroyItem()
is not called because the default implementation of Psger.getItemPosition()
returns PagerAdapter.POSITION_UNCHANGED
. So when you call PagerAdapter.notifyDataSetChanged()
ViewPager
continues to think that items you removed still exist and doesn't destroy them. You need to return PagerAdapter.POSITION_NONE
for each item removed from the adapter.
Upvotes: 2