实现ViewPager和ViewPager2的Fragment懒加载

本文介绍ViewPager和ViewPager2的懒加载如何实现,不谈为什么要懒加载。使用Kotlin代码。

ViewPager和ViewPager2都是继承与ViewGroup类,且运用方式大同小异,但也有一些差异。

由于ViewPager一直都有迭代,文章开始前,这里先抛出开发环境:

Android Stdio Bumblebee

plugins {
    id 'com.android.application' version '7.1.3' apply false
    id 'com.android.library' version '7.1.3' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
}

android {
    ...
    defaultConfig {
        ...
        minSdk 26
        targetSdk 32
        ...
    }
    ...
}

ViewPager+Fragment需要使用 FragmentStatePagerAdapter 适配器,而ViewPager2+Fragment需要使用FragmentStateAdapter 适配器。文章前半部分先介绍ViewPager+Fragment的懒加载实现,后半部分介绍ViewPager2+Fragment的。目前SDK32的androidx环境已集成ViewPager、ViewPager2相关内容,本文中提到的也是用的这些。

ViewPager+Fragment的懒加载实现

实际上是3部分:ViewPager | Fragment | FragmentStatePagerAdapter

但我们需要操刀的只有Fragment 和 FragmentStatePagerAdapter

继承于Fragment的Base类,载入适配器的Fragment必须继承于此类:

abstract class ViewPagerFragmentLazy : Fragment() {

    private var rootView: View? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
     rootView = createView(inflater, container, savedInstanceState)
     return rootView
}
   abstract fun createView(inflater: LayoutInflater,
                            container: ViewGroup?,
                            savedInstanceState: Bundle?): View

    override fun onResume() {
        super.onResume(
        lazyLoad(rootView!!)
    }

    override fun onPause() {
        super.onPause()
        stopLoad()
    }

   // 加载你的内容
abstract fun lazyLoad(view: View)
   // 当页面被划出,或者Fragment被遮挡,停止加载(简单的说,看不到了就停止)
abstract fun stopLoad() }

适配器类:

class ViewPagerFragmentAdapter(
    fm: FragmentManager,
    var fragmentTitles: MutableList<String>? = null,
    var fragments: MutableList<Fragment>? = null)
    : FragmentStatePagerAdapter(fm, FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

    init {
        if (null == fragmentTitles || null == fragments) {
            useDefaultTestData()
        }
    }

    private fun useDefaultTestData() {
        if (null == fragmentTitles) {
            // 标题
            fragmentTitles = arrayListOf("1", "2", "3", "4", "5")
        }
        if (null == fragments) {
            // Fragment extender ViewPagerFragmentLazy 
            fragments = ArrayList<Fragment>(fragmentTitles!!.size)
            fragments?.add(HomeFragment2())
            fragments?.add(DashboardFragment())
            fragments?.add(NotificationsFragment())
            fragments?.add(HomeFragment2())
            fragments?.add(HomeFragment2())
        }
    }

    override fun getCount(): Int {
        return if (fragmentTitles!!.size == fragments!!.size) {
            fragments!!.size
        } else {
            0
        }
    }

    // 获取标题
    fun getItemTitle(position: Int): String {
        return fragmentTitles!![position]
    }
    
    override fun getItem(position: Int): Fragment {
        return fragments!![position]
    }

    override fun getItemPosition(`object`: Any): Int {
        return POSITION_NONE
    }
}

Activity中实现:

class MainActivity2 : FragmentActivity() {

    private lateinit var bindingTest2: LayoutViewpagerTest2Binding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        test2()
    }

    fun test2() {
        bindingTest2 = LayoutViewpagerTest2Binding.inflate(layoutInflater)
        setContentView(bindingTest2.root)
        val viewPager = bindingTest2.viewPager
        viewPager.adapter = ViewPagerFragmentAdapter(supportFragmentManager)
 } }

ViewPager2+Fragment的懒加载实现

需要操刀的只有Fragment 和 FragmentStateAdapter

继承于Fragment的Base类,载入适配器的Fragment必须继承于此类:

abstract class Test1ViewPager2FragmentLazy : Fragment() {

    private var rootView: View? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        rootView = createView(inflater, container, savedInstanceState)
        return rootView
    }

    override fun onResume() {
        super.onResume()
        lazyLoad(rootView!!)
    }

    override fun onPause() {
        super.onPause()
        stopLoad()
    }

    abstract fun createView(inflater: LayoutInflater,
                            container: ViewGroup?,
                            savedInstanceState: Bundle?): View

    abstract fun lazyLoad(view: View)

    abstract fun stopLoad()
}

适配器类:

class Test1ViewPager2FragmentAdapter(private val fragmentActivity: FragmentActivity)
    : FragmentStateAdapter(fragmentActivity) {

    private val fragments : SparseArray<Fragment> = SparseArray()

    init {
        fragments.put(PAGE_HOME, HomeFragment())
        fragments.put(PAGE_DASHBOARD, DashboardFragment())
        fragments.put(PAGE_NOTIFICATIONS, NotificationsFragment())
        fragments.put(PAGE_OTHER1, HomeFragment())
        fragments.put(PAGE_OTHER2, HomeFragment())
    }

    companion object {
        const val PAGE_HOME = 0
        const val PAGE_DASHBOARD = 1
        const val PAGE_NOTIFICATIONS = 2
        const val PAGE_OTHER1 = 3
        const val PAGE_OTHER2 = 4
    }

    override fun getItemCount(): Int {
        return fragments.size()
    }

    override fun createFragment(position: Int): Fragment {
        return fragments[position]
    }
}

Activity中实现:

class MainActivity2 : FragmentActivity() {

    private lateinit var bindingTest1: LayoutViewpagerTest1Binding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        test1()
    }

    private fun test1() {
        bindingTest1 = LayoutViewpagerTest1Binding.inflate(layoutInflater)
        setContentView(bindingTest1.root)
        val viewPager2 = bindingTest1.viewPager
        val adapter = Test1ViewPager2FragmentAdapter(this)
        viewPager2.adapter = adapter
        viewPager2.offscreenPageLimit = 1
    }
}

总结

从以上代码中可以发现,SDK32中的ViewPager和ViewPager2的加载器有所不同,但是懒加载的 Base Fragmen 已经一样了!!

同时,因为已经使用了Lifecycle来管理Fragment的生命周期,所以,嵌套的问题,不存在

 

posted @ 2022-10-29 16:55  swalka`x  阅读(1790)  评论(0)    收藏  举报