重新创建 Activity 并重新启动 ViewPager2 时,requireContext() 和 requireView() 为 null

问题描述 投票:0回答:1

当在 Android 设备的设置应用程序中更改字体大小时,将重新创建 Activity。此时,当从 Activity 访问 Fragment 的功能时,requireContext() 和 requireView() 为 null,并且未启动 viewModel。

这是我的代码

活动

    var pagerAdapter: NewPagerAdapter? = null
    fun initView(){
        val vpContent = findViewById<ViewPager2>(R.id.vp_content)
        val fragmentList = ArrayList<ParentFragment>()
        fragmentList.add(FristFragment())
        fragmentList.add(SecondFragment())
        fragmentList.add(ThirdFragment())
        pagerAdapter = NewPagerAdapter(fragmentList, supportFragmentManager, lifecycle)
        vpContent.adapter = pagerAdapter

        val btnRefresh = findViewById<Button>(R.id.btn_scm_refresh)
        btnRefresh.setOnClickListener {
            (pagerAdapter)!!.allRefreshPage()
        }
    }

适配器

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

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

    fun allRefreshPage(context: Context){
        for(i in 0 until fragmentList.size){
            fragmentList[i].refreshData()
        }
    }

父片段

abstract class ParentFragment : Fragment() {
    abstract fun refreshData()
}

子片段

    private lateinit var viewModel: NewViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel = ViewModelProvider(this, ViewModelFactory())[NewViewModel::class.java]
    }


    override fun refreshData() {
        if(context == null || view == null) {
            Log.w(TAG, "refreshData: have not context or view")
            return
        }
        viewModel.initAppList(requireContext(), requireView())
    }

  1. 为什么会出现这种情况?

  2. 如何确保 null 不会出现?

  3. 还有其他方法可以将其作为活动中片段的函数来处理吗?

android android-fragments android-activity
1个回答
0
投票

1/为什么会发生这种情况?

PagerAdapter的fragmentList只保存Fragment实例以在需要时设置数据,不应该使用fragment变量来更新UI。尽管片段已启动,但它尚未附加到活动(用户尚未将选项卡滚动到该位置)。如果未附加

Fragment
,则
getContext
getActivity
始终为空

您的

ViewModel
可能没有创建在正确的位置,如Fragment的onCreate文档中所述:

请注意,这可以在片段的活动仍在时调用 被创造的过程。因此,您不能依赖诸如 此时活动的内容视图层次结构正在初始化

阅读此参考资料

2/如何确保不会出现null?

正如我所说,不要使用Adapter中的Fragment列表来更新Fragment的数据,这可能会触发UI更新

3/是否有其他方法可以将其作为活动中片段的函数来处理?

a/ 您应该使用

by activityViewModels
委托来创建 ViewModel 以避免在错误的位置创建 ViewModel,并且
activityViewModels
将确保您的 ViewModel 附加到 Activity 实例,Activity 和 Fragment 都为您提供相同的 ViewModel 实例这样您就可以在
Activity
Fragment

之间共享数据
private val viewModel by activityViewModels<TextClassifyViewModel>()

b/ 将数据存储在

LiveData
内的
ViewModel
中,然后从
Fragment
中观察。这样,每次重新创建 Fragment 时,
LiveData
都会再次触发数据以使视图保持最新。无需每次都打电话
refreshData

© www.soinside.com 2019 - 2024. All rights reserved.