John D.
John D.

Reputation: 2599

Android ViewPager - How to force removal of all items?

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

Answers (1)

Michael
Michael

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

Related Questions