ViewPager动态初始化最优方案

本文探讨了如何在ViewPager中动态初始化和管理Fragment,包括在数据变化后添加新Tab并调整顺序的实现方法。通过缓存Fragment、ItemId和Tab的上一次排序位置,实现了高效的刷新策略,当Tab顺序改变时,能正确地重新初始化或保持不变。更新Tab列表时,通过调用`notifyDataSetChanged()`触发刷新。
摘要由CSDN通过智能技术生成

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>()

初始化的顺序

  1. instantiateItem
  2. getItemId
    //如果没有找到Fragment, 就调用下面getItem获取fragment
  3. 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()
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态添加 Fragment 到 ViewPager 中,需要使用 FragmentPagerAdapter 或 FragmentStatePagerAdapter。以下是添加 Fragment 的步骤: 1. 创建 FragmentPagerAdapter 或 FragmentStatePagerAdapter 的子类: ``` public class MyPagerAdapter extends FragmentPagerAdapter { private List<Fragment> mFragmentList = new ArrayList<>(); public MyPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } public void addFragment(Fragment fragment) { mFragmentList.add(fragment); notifyDataSetChanged(); } } ``` 在这个子类中,我们需要重写 getItem() 方法,返回指定位置的 Fragment 对象;重写 getCount() 方法,返回 Fragment 的数量;还需要添加一个 addFragment() 方法,用于添加 Fragment。 2. 创建 ViewPager 对象,并设置 Adapter: ``` ViewPager viewPager = findViewById(R.id.viewpager); MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter); ``` 3. 创建 Fragment 对象: ``` MyFragment fragment = new MyFragment(); ``` 4. 添加 Fragment 到 Adapter: ``` adapter.addFragment(fragment); ``` 5. 刷新 Adapter: ``` adapter.notifyDataSetChanged(); ``` 这样就添加了一个 Fragment 到 ViewPager 中。如果需要替换 ViewPager 中的 Fragment,可以使用 setItem() 方法,方法参数是要替换的 Fragment 对象和位置。如果需要从 ViewPager 中移除 Fragment,可以使用 removeItem() 方法,方法参数是要移除的位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值