FragmentPagerAdapter VS FragmentStatePagerAdapter

James Lin
6 min readOct 28, 2018

--

FragmentPagerAdapter

假如需要將 ViewPager 與 Fragment 關聯在一起的話,就可以使用這個 Adapter,但是僅限於 ViewPager 的頁數不多的狀況下,因為這一個 Adapter 沒有回收 Fragment 的機制。

當 Fragment 不被使用者看見時,此 Adapter 會執行 FragmentTransation 的 Detach(純粹銷毀畫面),如果要讓使用者看見時,就會執行 FragmentTransation 的 Attach。

簡單來說,Fragment 不會從 FragmentManager 中移除,所以記憶體會越吃越多。

如果 ViewPager 的頁數很多的話,那麼 FragmentManager 就必須管理大量的 Fragment,這就是為什麼不適合用於大量資料。

使用方法:

MainActivity

var fmList = ArrayList<Fragment>()
fmList.add(ItemFragment.newInstance(0))
fmList.add(ItemFragment.newInstance(1))
fmList.add(ItemFragment.newInstance(2))
fmList.add(ItemFragment.newInstance(3))
fmList.add(ItemFragment.newInstance(4))
fmList.add(ItemFragment.newInstance(5))
fmList.add(ItemFragment.newInstance(6))
var fragmentAdapter = ContentStateAdapter(supportFragmentManager, fmList)
viewPager.adapter = fragmentAdapter

ContentStateAdapter

class ContentStateAdapter(fm: FragmentManager, val fmList: ArrayList<Fragment>)
: FragmentStatePagerAdapter(fm) {


override fun getItem(position: Int): Fragment {
return fmList[position]
}

override fun getCount(): Int = fmList.size
}

執行結果

一開始 Create 之後就沒有被 Destroy

要等到完全退出 Activity 之後才會全部 Destroy

FragmentStatePagerAdapter

這個 Adapter 與前述的 PagerAdpter 所使用的方法不太一樣,FragmentStatePagerAdapter 所用的機制是 add / remove,是真的把 Fragment 從 FragmentManager 中移除。

使用方法與 FragmentPagerAdapter 沒什麼不同

MainActivity

var fmList = ArrayList<Fragment>()
fmList.add(ItemFragment.newInstance(0))
fmList.add(ItemFragment.newInstance(1))
fmList.add(ItemFragment.newInstance(2))
fmList.add(ItemFragment.newInstance(3))
fmList.add(ItemFragment.newInstance(4))
fmList.add(ItemFragment.newInstance(5))
fmList.add(ItemFragment.newInstance(6))
var fragmentAdapter = ContentStateAdapter(supportFragmentManager, fmList)
viewPager.adapter = fragmentAdapter

ContentStateAdapter

class ContentStateAdapter(fm: FragmentManager, val fmList: ArrayList<Fragment>)
: FragmentStatePagerAdapter(fm) {


override fun getItem(position: Int): Fragment {
return fmList[position]
}

override fun getCount(): Int = fmList.size
}

執行結果

每當使用者往後滑動時,前面的 Fragment 會被回收掉,只保留 當前的 Fragment 前後的 Fragment。

參考資料:
http://yifeng.studio/2016/12/19/android-fragment-state-saving-best-practices/

GitHub

--

--

James Lin
James Lin

No responses yet