ViewPager动态初始化最优方案
前景
默认初始化3个tab, 但是当联网获取到数据之后, 需要再新增一个tab,而且tab的顺序需要调整.
源码分析
定义变量缓存所需数据
//缓存fragment
private val fragments = mutableMapOf<Tab, Fragment>()
//缓存fragment的ItemId
private val keyIdMap = mutableMapOf<Tab, Int>()
//缓存tab的上一次的排序位置
private val prePosList = mutableListOf<Tab>()
初始化的顺序
- instantiateItem
- getItemId
//如果没有找到Fragment, 就调用下面getItem获取fragment - getItem
刷新方案
getItemPosition
通过fragments获得key(tab)
然后key获得新的newIndex
如果旧的index != newIndex,
清除缓存的fragment,清除id让其重新初始化
返回POSITION_NONE,让其重新初始化
其余返回 POSITION_UNCHANGED
源码
class MainPagePagerAdapter(fragmentManager: FragmentManager) :
FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
private var tabList = listOf<String>("Chat", "Camera", "Story")
private val FRAGMENT_SIZE: Int
get() = tabList.size
private val fragments = mutableMapOf<String, Fragment>()
private val keyIdMap = mutableMapOf<String, Int>()
private val prePosList = mutableListOf<String>()
private var id = 0
override fun getItem(position: Int): Fragment {
return getFragment(position)
}
private fun getFragment(position: Int): Fragment {
val tab = tabList[position]
var fragment = fragments[tab]
if (fragment == null) {
fragment = Fragment()
fragments[tab] = fragment
}
return fragment
}
override fun getItemId(position: Int): Long {
//这个方法是通过itemId来获取fragment,所以要自己管理一份id
val key = tabList[position]
var savedId = keyIdMap[key]?.toLong()
if (savedId == null) {
savedId = (id).toLong()
keyIdMap[key] = id++
}
return savedId
}
override fun getCount(): Int {
return FRAGMENT_SIZE
}
override fun getItemPosition(`object`: Any): Int {
var key: String? = null
//找出fragment对应的key
fragments.forEach loop@{
if (it.value == `object`) {
key = it.key
return@loop
}
}
if (key == null) {
return POSITION_UNCHANGED
}
//取出旧的位置, 对比新的位置, 如果不相等就需要重新创建实例
val index = prePosList.indexOf(key!!)
var newIndex = -1
tabList.forEachIndexed { i, tab ->
if (tab == key) {
newIndex = i
}
}
if (index != newIndex) {
//清除缓存
fragments.remove(key!!)
keyIdMap.remove(key!!)
return POSITION_NONE
}
return POSITION_UNCHANGED
}
fun update(listOf: List<String>) {
prePosList.clear()
prePosList.addAll(tabList.toList())
tabList = listOf
notifyDataSetChanged()
}
}