美文网首页jetpack
Navigation学习笔记之二--fragment保存状态

Navigation学习笔记之二--fragment保存状态

作者: 紫鹰 | 来源:发表于2022-07-11 11:47 被阅读0次

fragment状态保存问题

在使用jetpack的navigation组件过程中遇到的一个问题就是它内部使用replace方式切换的fragment,这样会导致fragment生命周期重走。这样就不会保留之前的页面状态了,这就有点不友好了。查了一下大家使用的解决方案,主要有两种

  • 使用hide/show方式取代replace方式

  • 继续使用replace方式,想办法保存页面状态

经过对比这两种方案发现,navigation原生方式更合理。因为hide/show方案对内存不友好的弊端很难消除,且项目越大,问题越明显。

使用原生方式,就面临了另一个问题,如何保存页面状态?Navigation设计初衷就是UI与数据分离,所以这个问题,拆解成两个问题分别解决:

1.页面问题

Google官方有推荐方案,就是保存view。

abstract class BaseFragment : Fragment() {  
    private var rootView : View ?= null  

    override fun onCreateView(  
        inflater: LayoutInflater,  
        container: ViewGroup?,  
        savedInstanceState: Bundle?  
    ): View? {  
        if (rootView == null){  
             rootView = inflater.inflate(getLayoutId(), null)  
        }  
        return rootView  
    }  
    abstract fun getLayoutId():Int  
}

2.数据问题

通过viewmodel保存数据,这里引出两个问题

  • 1.viewmodel的生命周期跟随谁

跟随fragment,那么fragment销毁的时候,viewmodel就没有了。跟随activity,那么activcity不销毁的情况下,viewmodel就一直存在

看源码发现,Navigation切换fragment用的是childFragmentManager,所有的fragment的父fragment都是NavHostFragment,于是跟随requireParentFragment()就可以了

override fun initVM(): StickerViewModel = ViewModelProvider(requireParentFragment())[StickerViewModel::class.java]
  • 2.fragment重新创建的时,重新注册uiStatus的observer,注册的时候,livedata会把上次数据重新发送一遍。

解决方法也很简单,只需要在基类的fragment中清除一下状态就好了

还有一个问题,如果跳转fragment的时候,携带了参数,重新回到这个fragment的时候也会重新获取到。这个也是需要清除的

综合以上各种问题的解决方案,BaseFragment应当如下

abstract class BaseVMFragment<VM : BaseViewModel> : Fragment() {  

    protected var mContentView: View? = null  
    protected lateinit var mViewModel: VM  
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {  
        if (mContentView == null) {  
            mContentView = inflater.inflate(getLayoutResId(), container, false)  
        }  
        return mContentView  
    }  

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {  
        mViewModel = initVM()  
        if (isNeedClearState()) {  
            mViewModel.clearUIState()  
        }  
        initView()  
        initData()  
        startObserve()  
        super.onViewCreated(view, savedInstanceState)  
    }  

    override fun onDestroyView() {  
        //需要清除参数和uiState  
        arguments?.clear()  
        super.onDestroyView()  
    }  

    open fun isNeedClearState(): Boolean {  
        return true  
    }  

    abstract fun getLayoutResId(): Int  
    abstract fun initVM(): VM  
    abstract fun initView()  

    abstract fun initData()  

    abstract fun startObserve()  

}

相关文章

网友评论

    本文标题:Navigation学习笔记之二--fragment保存状态

    本文链接:https://www.haomeiwen.com/subject/lihnbrtx.html