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

mwkjh3gx  于 11个月前  发布在  Android
关注(0)|答案(1)|浏览(178)

在Android设备的设置app中更改Font Size时,Activity会被重新创建。此时,从Activity访问片段的函数时,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()
        }
    }


ParentFragment

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


ChildFragment

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.为什么会这样?
1.我怎样才能确保null不会出来呢?
1.有没有其他的方法来处理它作为活动中片段的函数?

ix0qys7i

ix0qys7i1#

1/为什么会这样?

PagerAdapter的fragmentList只保存Fragment示例,在需要的时候设置数据,不应该使用fragment变量来更新UI。虽然Fragment被初始化,但它还没有被附加到Activity(用户还没有将tab滚动到该位置)。如果Fragment没有被附加,则getContextgetActivity始终为null
您的ViewModel可能没有在正确的位置创建,如Fragment的onCreate文档中所述:
请注意,这可以在片段的Activity仍处于创建过程中时调用。
阅读此参考

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

正如我所说的,不要使用适配器中的Fragment列表来更新Fragment的数据,这可能会触发UI更新。始终确保任何更新UI和require Context的调用都在onViewCreated之后,您将在onViewCreatedonDestroyView之间获得非空的Context

3/是否有任何其他方法将其作为活动中片段的函数?

a/您应该使用by activityViewModels委托来创建ViewModel,以避免在错误的位置创建ViewModel,并且activityViewModels将确保您的ViewModel附加到Activity示例,Activity和Fragment给予相同的ViewModel示例,以便您可以在ActivityFragment之间共享数据

private val viewModel by activityViewModels<TextClassifyViewModel>()

字符串
B/将您的数据存储在ViewModel内部的LiveData中,然后从Fragment观察它。这样,每次重新创建片段时,LiveData都会再次触发数据以保持View最新。无需每次都调用refreshData

相关问题