美文网首页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