城市直播房产教育博客汽车
投稿投诉
汽车报价
买车新车
博客专栏
专题精品
教育留学
高考读书
房产家居
彩票视频
直播黑猫
投资微博
城市上海
政务旅游

JetpackMVVM七宗罪之一还在使用Fragment作为

3月11日 托天庙投稿
  Jetpack的MVVM本身没有错,错在开发者的某些使用不当。本文将分享那些AAC中常见的错误用法,以帮助大家打造更健康的应用架构Fragment作为LifecycleOwner的问题
  MVVM的核心是数据驱动UI,在Jetpack中,这一思想体现在以下场景:Fragment通过订阅ViewModel中的LiveData以驱动自身UI的更新
  关于订阅的时机,一般会选择放到onViewCreated中进行,如下:overridefunonViewCreated(view:View,savedInstanceState:Bundle?){super。onViewCreated(view,savedInstanceState)viewModel。liveData。observe(this){Warning:UsefragmentastheLifecycleOwnerupdateUI(it)}}
  我们知道订阅LiveData时需要传入LifecycleOwner以防止泄露,此时一个容易犯的错误是使用Fragment作为这个LifecycleOwner,某些场景下会造成重复订阅的Bug。
  做个实验如下:valhandlerHandler(Looper。getMainLooper())classMyFragment1:Fragment(){valdataMutableLiveDataInt()overridefunonViewCreated(view:View,savedInstanceState:Bundle?){super。onViewCreated(view,savedInstanceState)tv。setOnClickListener{parentFragmentManager。beginTransaction()。replace(R。id。container,MyFragment2())。addToBackStack(null)。commit()handler。post{data。value1}}data。observe(this,Observer{Log。e(fragment,count:{data。value})})}
  当跳转到MyFragment2然后再返回MyFragment1中时,会打出输出两条logEfragment:count:1Efragment:count:1原因分析
  LiveData之所以能够防止泄露,是当LifecycleOwner生命周期走到DESTROYED的时候会remove调其关联的ObserverLiveData。javaOverridepublicvoidonStateChanged(LifecycleOwnersource,Lifecycle。Eventevent){if(mOwner。getLifecycle()。getCurrentState()DESTROYED){removeObserver(mObserver);}activeStateChanged(shouldBeActive());}
  前面例子中,基于FragmentManagerreplace的页面跳转,使得MyFragment1发生了从BackStack的出栈入栈,由于Framgent实例被复用并没有发生onDestroy,但是Fragment的View的重建导致重新onCreateView,这使得Observer被add了两次,但是没有对应的remove。
  所以归其原因,是由于Fragment的Lifecycle与FragmentmView的Lifecycle不一致导致我们订阅LiveData的时机和所使用的LivecycleOwner不匹配,所以在任何基于replace进行页面切换的场景中,例如ViewPager、Navigation等会发生上述bug
  解决方法
  明白了问题原因,解决思路也就清楚了:必须要保证订阅的时机和所使用的LifecycleOwner相匹配,即要么调整订阅时机,要么修改LifecycleOwner
  在onCreate中订阅
  思路一是修改订阅时机,将订阅提前到onCreate,可以保证与onDestory的成对出现,但不幸的是这会带来另一个问题。
  当Fragment出入栈造成View重建时,我们需要重建后的View也能显示最新状态。但是由于onCreate中的订阅的Observer已经获取过LiveData的最新的Value,如果Value没有新的变化是无法再次通知Obsever的
  在LiveData源码中体现在通知Obsever之前对mLastVersion的判断:LiveData。javaprivatevoidconsiderNotify(ObserverWrapperobserver){if(!observer。mActive){}if(!observer。shouldBeActive()){observer。activeStateChanged(false);}if(observer。mLastVersionmVersion){Value已经处于最新的}observer。mLastVersionmVnoinspectionuncheckedobserver。mObserver。onChanged((T)mData);}
  正是为了保证重建后的View也能刷新最新的数据,我们才在onViewCreated中完成订阅。因此只能考虑另一个思路,替换LifecycleOwner
  使用ViewLifecycleOwner
  Support28或AndroidX1。0。0起,Fragment新增了getViewLifecycleOwner方法。顾名思义,它返回一个与FragmentmView相匹配的LifecycleOwner,可以在onDestroyView的时候走到DESTROYED,删除onCreateView中注册的Observer,保证了addremove的成对出现。
  看一下源码,原理非常简单Fragment。javavoidperformCreateView(NonNullLayoutInflaterinflater,NullableViewGroupcontainer,NullableBundlesavedInstanceState){。。。mViewLifecycleOwnernewLifecycleOwner(){OverridepublicLifecyclegetLifecycle(){if(mViewLifecycleRegistrynull){mViewLifecycleRegistrynewLifecycleRegistry(mViewLifecycleOwner);}returnmViewLifecycleR}};mViewLifecycleRmViewonCreateView(inflater,container,savedInstanceState);if(mView!null){InitializetheLifecycleRegistryifneededmViewLifecycleOwner。getLifecycle();TheninformanyObserversofthenewLifecycleOwnermViewLifecycleOwnerLiveData。setValue(mViewLifecycleOwner);mViewLifecycleOwnerLiveData在后文介绍}else{。。。}}
  基于mViewLifecycleRegistry创建mViewLifecycleOwner,CallSuperpublicvoidonViewStateRestored(NullableBundlesavedInstanceState){calledwhenonCreateViewif(mView!null){mViewLifecycleRegistry。handleLifecycleEvent(Lifecycle。Event。ONCREATE);}}CallSuperpublicvoidonDestroyView(){if(mView!null){mViewLifecycleRegistry。handleLifecycleEvent(Lifecycle。Event。ONDESTROY);}}
  然后在onCreateView和onDestroyView时,推进到合适的生命周期。
  getViewLifecycleOwnerLiveData
  顺道提一下,与getViewLifecycleOwner同时新增的还有getViewLifecycleOwnerLiveData。从前面贴的源码中对mViewLifecycleOwnerLiveData的使用,应该可以猜出它的作用:它是前文讨论的思路1的实现方案,即使在onCreate中订阅,由于在onCreateView中对LiveData进行了重新设置,所以重建后的View也可以更新数据。TheninformanyObserversofthenewLifecycleOwnermViewLifecycleOwnerLiveData。setValue(mViewLifecycleOwner);
  需要特别注意的是,根据MVVM最佳实践,我们希望由ViewModel而不是Fragment持有LiveData,所以不再推荐使用getViewLifecycleOwnerLiveData最后:StateFlow与lifecycleScope
  前面都是以LiveData为例介绍对ViewLifecycleOwner的使用,如今大家也越来越多的开始使用协程的StateFlow,同样要注意不要错用LifecycleOwner
  订阅StateFlow需要CoroutineScope,AndroidX提供了基于LifecycleOwner的扩展方法valLifecycleOwner。lifecycleScope:LifecycleCoroutineScopeget()lifecycle。coroutineScope
  当我们在Fragment中获取lifecycleScope时,切记要使用ViewLifecycleOwnerclassMyFragment:Fragment(){valviewModel:MyViewModelbyviewModel()overridefunonViewCreated(view:View,savedInstanceState:Bundle?){super。onViewCreated(view,savedInstanceState)使用viewLifecycleOwner的lifecycleScopeviewLifecycleOwner。lifecycleScope。launch{viewLifecycleOwner。repeatOnLifecycle(Lifecycle。State。STARTED){viewModel。someDataFlow。collect{updateUI(it)}}}}}
  注意此处出现了一个repeatOnLifecycle(。。。),这跟本文无关,但是将涉及到下一宗罪的剧情,敬请期待。最后
  在这里就还分享一份由大佬亲自收录整理的Android学习PDF架构视频面试文档源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料
  这些都是我现在闲暇时还会反复翻阅的精品资料。里面对近几年的大厂面试高频知识点都有详细的讲解。相信可以有效地帮助大家掌握知识、理解原理,帮助大家在未来取得一份不错的答卷。
  当然,你也可以拿去查漏补缺,提升自身的竞争力。
  真心希望可以帮助到大家,Android路漫漫,共勉!
  如果你有需要的话,只需私信我【进阶】即可获取
投诉 评论 转载

智慧医疗智慧城市数据中心5G,股价强势向上突破,还能进场吗一、热门个股解读万马科技(300698)二、后市分析万马科技(300698)该公司的产品包含通信网络配线及信息化机柜产品和医疗信息化产品两大类。公司最赚钱的业务就是……Cruise再获投13。5亿美元!CBD开放RoboTaxi知一发自大年初二智能车参考公众号AI4Auto自动驾驶领域,又一巨款。13。5亿美元,折合人民币85。87亿元,流向Cruise。最新消息,孙正义旗下软……曾经非常火爆的微商为什么现在很少人做了?微商我也开过店铺,给我的印象微商太利益攻心了,收钱买流量,而且还没有流量谁会继续做下去,还有很多人不习惯在微商买东西,腾讯想在电商领域分蛋糕太难了,老老实实做合作伙伴还可以,例……马斯克玩火特斯拉暴跌12,工信部批复组建国家5G中高频器件中国际方面:美股收跌,标普跌0。35、道指跌0。31、纳指跌0。6;新能源车全线走低,特斯拉大跌12;元宇宙概念股ROBLOX涨42;油价上涨,美油涨2;英伟达发布最新虚拟世界创……文萃数据垄断探析来源:读特编者按随着数字经济向纵深发展,数据作为一种新型生产要素,已然成为数字信息时代先进生产力发展的重要驱动力,成为互联网企业的核心资产。随着数据的累积,不同企业……华为P50系列爆料汇总,麒麟9000处理器鸿蒙OS体验超出你【华为P50系列爆料汇总】6月2日华为将正式发布鸿蒙OS手机版系统,大家都在幻想,如果华为P50系列也能在该场发布会上与我们见面那该多好呀!那么接下来我就来给大家汇总一下……苹果iphone13pro和iphone12pro区别点在哪ppleiphone13pro手机在昨晚发布了,那它和上一代iphone12pro手机相比较有哪些提升呢,下面跟着小编一起来看看。一、相同点1。苹果iphone13……资深玩机党在线分享高性价比手机这两款要仔细看如今,手机市场的竞争愈发激烈,这对于我们普通消费者来说,一方面是好事选择变得更多了,一方面也有缺点,那就是在这样的环境中就更难找到最值得的机型了。今天,我就为大家推荐几款以性价……搬离中国后富士康损失惨重,郭台铭又想回来了?富士康损失惨重富士康集团是国内乃至全球最大的电子产品代工厂,在很多国家和地区都建设了生产线,并且拥有数万名员工。但是整体来看,富士康的业务重心仍然是在国内市场,尤其是苹果……漂亮的实力派杜伽K330W无线三模机械键盘Y1S1,我柜子里的杜伽产品库好久没有更新了,虽然知道杜伽已经出了K330W,但阴差阳错之下,一直没有到手一把,这次终于如愿以偿。DURGOD杜伽K330W无线蓝牙三模键盘,采……JetpackMVVM七宗罪之一还在使用Fragment作为Jetpack的MVVM本身没有错,错在开发者的某些使用不当。本文将分享那些AAC中常见的错误用法,以帮助大家打造更健康的应用架构Fragment作为LifecycleOwne……将神光棒戴在手上是一种什么样的体验?为了纪念迪迦奥特曼25周年,Benelic推出了一款迪迦奥特曼神光棒(火花棱镜)的手表,那么这款产品做得到底怎么样,我们一起来看看吧!官图鉴赏这款手表整体采用了迪迦……
等等党终将胜利!蔚来新品牌杀入平民市场,比特斯拉便宜还服务好为何说IT科技公司应该留住35岁员工?小米出价格5000元以上的手机你会买吗?宁德时代又急了钱放微信还是余额宝好?全球首富马斯克!粉丝突破9042万,为什么要重金收购推特?在武汉当一名出租车司机,月收入能过4000吗?以画笔展现科技成就,为科技工作者立传飞书以先进工具塑造新组织形态,让信息如水一般流动WISE20iPhone13保护壳曝光,外观基本上确定了小鹏汽车2021年营收210亿元,同比增长259青花郎暂停接收订单天猫已告罄下架汪俊林此前称卖完了就没有了
梅兰芳的简介(梅兰芳情史录)夏天谨防车内易爆物品金鱼身子歪了是怎么回事,怎么治疗丹宁风外套搭配技巧文咏珊豪门少奶奶生活与平民无分别网民疑惑为什么要嫁人常满造句用常满造句大全防溺水发言稿宝马i3充上电电量170个实际步骤帮助你减少恐惧中班打击乐小看戏孔雀石是什么?孔雀石的功效与作用开庭判决后的借条可以二次起诉么热议聚热点网

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找江西南阳嘉兴昆明铜陵滨州广东西昌常德梅州兰州阳江运城金华广西萍乡大理重庆诸暨泉州安庆南充武汉辽宁