1.Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
2.AndroidMVVM
3.Android篇MVVM 到 MVI:迁移 Android 架构
4.androidui设计mvvm设计模式讨论?
5.Android mvvm 之 databinding 原理
6.Android-MVVM-Databinding的原理、用法与封装
Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
Android UI架构的hadoop avatar 源码演变:从MVC到MVP、MVVM和MVI
随着Android开发的发展,为优化代码设计,业界不断探索和实践不同的架构模式,如MVC、MVP、MVVM和MVI,它们的核心目标是“关注点分离”,以提高代码的可维护性、测试性和可读性。最初,所有UI逻辑都集中在Activity中,导致高度耦合,难以管理。 1. MVC:Android的默认设计,将代码划分为Model、View和Controller,尽管解决了Activity代码过载问题,但Activity仍承担了View和逻辑处理的双重任务,分离不够彻底。 2. MVP:为了解决MVC的不足,MVP将逻辑分离到Presenter,app代码源码学习使用Contract接口定义View和Presenter的交互。但双向依赖仍是其缺点。 3. MVVM:MVVM将Presenter变为ViewModel,使用观察者模式减少双向依赖。DataBinding等工具支持了MVVM的实现,但过度使用可能导致数据流混乱。 4. MVI:MVI强调单数据流,通过ViewState简化View和ViewModel之间的交互。虽然更注重响应式,但过度压缩状态可能导致复杂性。 总的来说,MVP、MVVM和MVI都试图将Activity的职责分解,但每种模式都有其局限性和适用场景。MVVM和MVP本质上相似,而MVI则引入了命令式到响应式的转变。选择哪种架构,应根据项目的具体需求和团队习惯来决定,而不是盲目追求新潮。AndroidMVVM
æ¦è¿°è¯´å°Android MVVMï¼ç¸ä¿¡å¤§å®¶é½ä¼æ³å°Google å¹´æ¨åºçDataBindingæ¡æ¶ãç¶è两è çæ¦å¿µæ¯ä¸ä¸æ ·çï¼ä¸è½æ··ä¸ºä¸è°ãMVVMæ¯ä¸ç§æ¶æ模å¼ï¼èDataBindingæ¯ä¸ä¸ªå®ç°æ°æ®åUIç»å®çæ¡æ¶ï¼æ¯æ建MVVM模å¼çä¸ä¸ªå·¥å ·ã
ä¹åçè¿å¾å¤å ³äºAndroid MVVMçå客ï¼ä½å¤§å¤æ°æå°çé½æ¯DataBindingçåºæ¬ç¨æ³ï¼å¾å°ææç« ä»ç»è®²è§£å¨Androidä¸æ¯å¦ä½éè¿DataBindingå»æ建MVVMçåºç¨æ¡æ¶çãViewãViewModelãModelæ¯ä¸å±çèè´£å¦ä½?å®ä»¬ä¹é´èç³»ææ ·ãåå·¥å¦ä½ã代ç åºè¯¥å¦ä½è®¾è®¡?è¿æ¯æåè¿ç¯æç« çåè¡·ã
æ¥ä¸æ¥ï¼æ们å æ¥ççä»ä¹æ¯MVVMï¼ç¶ååä¸æ¥ä¸æ¥æ¥è®¾è®¡æ´ä¸ªMVVMæ¡æ¶ã
MVCãMVPãMVVM
é¦å ï¼æ们å 大è´äºè§£ä¸Androidå¼åä¸å¸¸è§ç模å¼ã
MVC
Viewï¼XMLå¸å±æ件ã
Modelï¼å®ä½æ¨¡å(æ°æ®çè·åãåå¨ãæ°æ®ç¶æåå)ã
Controllorï¼å¯¹åºäºActivityï¼å¤çæ°æ®ãä¸å¡åUIã
ä»ä¸é¢è¿ä¸ªç»ææ¥çï¼Androidæ¬èº«ç设计è¿æ¯ç¬¦åMVCæ¶æçï¼ä½æ¯Androidä¸çº¯ç²¹ä½ä¸ºViewçXMLè§å¾åè½å¤ªå¼±ï¼æ们大éå¤çViewçé»è¾åªè½åå¨Activityä¸ï¼è¿æ ·Activityå°±å å½äºViewåController两个è§è²ï¼ç´æ¥å¯¼è´Activityä¸ç代ç 大çç¸ãç¸ä¿¡å¤§å¤æ°Androidå¼åè é½éå°è¿ä¸ä¸ªAcitivtyæ°ä»¥åè¡ç代ç æ åµå§!æ以ï¼æ´è´´åç说æ³æ¯ï¼è¿ä¸ªMVCç»ææç»å ¶å®åªæ¯ä¸ä¸ªModel-View(Activity:View&Controller)çç»æã
MVP
View: 对åºäºActivityåXMLï¼è´è´£Viewçç»å¶ä»¥åä¸ç¨æ·ç交äºã
Model: ä¾ç¶æ¯å®ä½æ¨¡åã
Presenter: è´è´£å®æViewä¸Modelé´ç交äºåä¸å¡é»è¾ã
åé¢æ们说ï¼Activityå å½äºViewåController两个è§è²ï¼MVPå°±è½å¾å¥½å°è§£å³è¿ä¸ªé®é¢ï¼å ¶æ ¸å¿ç念æ¯éè¿ä¸ä¸ªæ½è±¡çViewæ¥å£(ä¸æ¯çæ£çViewå±)å°Presenterä¸çæ£çViewå±è¿è¡è§£è¦ãPersenterææ该Viewæ¥å£ï¼å¯¹è¯¥æ¥å£è¿è¡æä½ï¼èä¸æ¯ç´æ¥æä½Viewå±ãè¿æ ·å°±å¯ä»¥æè§å¾æä½åä¸å¡é»è¾è§£è¦ï¼ä»è让Activityæ为çæ£çViewå±ã
ä½MVPä¹åå¨ä¸äºå¼ç«¯ï¼
Presenter(以ä¸ç®ç§°P)å±ä¸View(以ä¸ç®ç§°V)å±æ¯éè¿æ¥å£è¿è¡äº¤äºçï¼æ¥å£ç²åº¦ä¸å¥½æ§å¶ãç²åº¦å¤ªå°ï¼å°±ä¼åå¨å¤§éæ¥å£çæ åµï¼ä½¿ä»£ç 太è¿ç¢çå;ç²åº¦å¤ªå¤§ï¼è§£è¦ææä¸å¥½ãåæ¶å¯¹äºUIçè¾å ¥åæ°æ®çååï¼éè¦æå¨è°ç¨Vå±æè På±ç¸å ³çæ¥å£ï¼ç¸å¯¹æ¥è¯´ç¼ºä¹èªå¨æ§ãçå¬æ§ãå¦ææ°æ®çååè½èªå¨ååºå°UIãUIçè¾å ¥è½èªå¨æ´æ°å°æ°æ®ï¼é£è¯¥å¤å¥½!
MVPæ¯ä»¥UI为驱å¨ç模åï¼æ´æ°UIé½éè¦ä¿è¯è½è·åå°æ§ä»¶çå¼ç¨ï¼åæ¶æ´æ°UIçæ¶åè¦èèå½åæ¯å¦æ¯UI线ç¨ï¼ä¹è¦èèActivityççå½å¨æ(æ¯å¦å·²ç»éæ¯ç)ã
MVPæ¯ä»¥UIåäºä»¶ä¸ºé©±å¨çä¼ ç»æ¨¡åï¼æ°æ®é½æ¯è¢«å¨å°éè¿UIæ§ä»¶åå±ç¤ºï¼ä½æ¯ç±äºæ°æ®çæ¶åæ§ï¼æ们æ´å¸ææ°æ®è½è½¬è¢«å¨ä¸ºä¸»å¨ï¼å¸ææ°æ®è½æ´ææ´»æ§ï¼ç±æ°æ®æ¥é©±å¨UIã
Vå±ä¸På±è¿æ¯æä¸å®çè¦å度ãä¸æ¦Vå±æ个UIå ç´ æ´æ¹ï¼é£ä¹å¯¹åºçæ¥å£å°±å¿ é¡»å¾æ¹ï¼æ°æ®å¦ä½æ å°å°UIä¸ãäºä»¶çå¬æ¥å£è¿äºé½éè¦è½¬åï¼çµä¸åèå¨å ¨èº«ãå¦æè¿ä¸å±ä¹è½è§£è¦å°±æ´å¥½äºã
å¤æçä¸å¡åæ¶ä¹å¯è½ä¼å¯¼è´På±å¤ªå¤§ï¼ä»£ç èè¿çé®é¢ä¾ç¶ä¸è½è§£å³ã
MVVM
View: 对åºäºActivityåXMLï¼è´è´£Viewçç»å¶ä»¥åä¸ç¨æ·äº¤äºã
Model: å®ä½æ¨¡åã
ViewModel: è´è´£å®æViewä¸Modelé´ç交äºï¼è´è´£ä¸å¡é»è¾ã
MVVMçç®æ åææ³ä¸MVP类似ï¼å©ç¨æ°æ®ç»å®(Data Binding)ãä¾èµå±æ§(Dependency Property)ãå½ä»¤(Command)ãè·¯ç±äºä»¶(Routed Event)çæ°ç¹æ§ï¼æé äºä¸ä¸ªæ´å çµæ´»é«æçæ¶æã
æ°æ®é©±å¨
å¨å¸¸è§çå¼å模å¼ä¸ï¼æ°æ®ååéè¦æ´æ°UIçæ¶åï¼éè¦å è·åUIæ§ä»¶çå¼ç¨ï¼ç¶ååæ´æ°UIãè·åç¨æ·çè¾å ¥åæä½ä¹éè¦éè¿UIæ§ä»¶çå¼ç¨ãå¨MVVMä¸ï¼è¿äºé½æ¯éè¿æ°æ®é©±å¨æ¥èªå¨å®æçï¼æ°æ®åååä¼èªå¨æ´æ°UIï¼UIçæ¹åä¹è½èªå¨åé¦å°æ°æ®å±ï¼æ°æ®æ为主导å ç´ ãè¿æ ·MVVMå±å¨ä¸å¡é»è¾å¤çä¸åªè¦å ³å¿æ°æ®ï¼ä¸éè¦ç´æ¥åUIæ交éï¼å¨ä¸å¡å¤çè¿ç¨ä¸ç®åæ¹ä¾¿å¾å¤ã
ä½è¦å度
MVVM模å¼ä¸ï¼æ°æ®æ¯ç¬ç«äºUIçã
æ°æ®åä¸å¡é»è¾å¤äºä¸ä¸ªç¬ç«çViewModelä¸ï¼ViewModelåªéè¦å ³æ³¨æ°æ®åä¸å¡é»è¾ï¼ä¸éè¦åUIæè æ§ä»¶æ交éãUIæ³æä¹å¤çæ°æ®é½ç±UIèªå·±å³å®ï¼ViewModelä¸æ¶åä»»ä½åUIç¸å ³çäºï¼ä¹ä¸ææUIæ§ä»¶çå¼ç¨ãå³ä¾¿æ¯æ§ä»¶æ¹åäº(æ¯å¦ï¼TextViewæ¢æEditText)ï¼ViewModelä¹å ä¹ä¸éè¦æ´æ¹ä»»ä½ä»£ç ãå®é常å®ç¾ç解è¦äºViewå±åViewModelï¼è§£å³äºä¸é¢æ们æ说çMVPççç¹ã
æ´æ°UI
å¨MVVMä¸ï¼æ°æ®åçåååï¼æ们å¨å·¥ä½çº¿ç¨ç´æ¥ä¿®æ¹(å¨æ°æ®æ¯çº¿ç¨å®å ¨çæ åµä¸)ViewModelçæ°æ®å³å¯ï¼ä¸ç¨åèèè¦åå°ä¸»çº¿ç¨æ´æ°UIäºï¼è¿äºäºæ ç¸å ³æ¡æ¶é½å¸®æ们åäºã
å¢éåä½
MVVMçåå·¥æ¯é常ææ¾çï¼ç±äºViewåViewModelä¹é´æ¯æ¾æ£è¦åçï¼ä¸ä¸ªæ¯å¤çä¸å¡åæ°æ®ãä¸ä¸ªæ¯ä¸é¨çUIå¤çãæ以ï¼å®å ¨ç±ä¸¤ä¸ªäººåå·¥æ¥åï¼ä¸ä¸ªåUI(XMLåActivity)ä¸ä¸ªåViewModelï¼æçæ´é«ã
å¯å¤ç¨æ§
ä¸ä¸ªViewModelå¯ä»¥å¤ç¨å°å¤ä¸ªViewä¸ãåæ ·çä¸ä»½æ°æ®ï¼å¯ä»¥æä¾ç»ä¸åçUIå»åå±ç¤ºã对äºçæ¬è¿ä»£ä¸é¢ç¹çUIæ¹å¨ï¼æ´æ°ææ°å¢ä¸å¥Viewå³å¯ãå¦ææ³å¨UIä¸åA/B Testingï¼é£MVVMæ¯ä½ ä¸äºéæ©ã
åå æµè¯
æäºåå¦ä¸çå°åå æµè¯ï¼å¯è½èè¢é½å¤§ãæ¯åï¼åæä¸å¢æµç³ç代ç æä¹å¯è½ååå æµè¯?å¦æä½ ä»¬ä»¥ä»£ç 太çæ æ³ååå æµè¯èéé¿ï¼é£å¯çæ¯ä¸å¥½çæ¶æ¯äºãè¿æ¶åï¼ä½ éè¦MVVMæ¥æ¯æã
æ们åé¢è¯´è¿äºï¼ViewModelå±åçäºæ¯æ°æ®å¤çåä¸å¡é»è¾ï¼Viewå±ä¸å ³æ³¨çæ¯UIï¼ä¸¤è å®å ¨æ²¡æä¾èµãä¸ç®¡æ¯UIçåå æµè¯è¿æ¯ä¸å¡é»è¾çåå æµè¯ï¼é½æ¯ä½è¦åçãå¨MVVMä¸æ°æ®æ¯ç´æ¥ç»å®å°UIæ§ä»¶ä¸ç(é¨åæ°æ®æ¯å¯ä»¥ç´æ¥åæ åºUIä¸çå 容)ï¼é£ä¹æ们就å¯ä»¥ç´æ¥éè¿ä¿®æ¹ç»å®çæ°æ®æºæ¥é´æ¥åä¸äºAndroid UIä¸çæµè¯ã
éè¿ä¸é¢çç®è¿°ä»¥å模å¼ç对æ¯ï¼æ们å¯ä»¥åç°MVVMçä¼å¿è¿æ¯é常ææ¾çãè½ç¶ç®åAndroidå¼åä¸å¯è½çæ£å¨ä½¿ç¨MVVMçå¾å°ï¼ä½æ¯å¼å¾æ们å»åä¸äºæ¢è®¨åè°ç ã
å¦ä½æ建MVVMåºç¨æ¡æ¶
å¦ä½åå·¥
æ建MVVMæ¡æ¶é¦å è¦å ·ä½äºè§£å个模åçåå·¥ãæ¥ä¸æ¥æ们æ¥è®²è§£ViewãViewModelãModelå®ä»¬åèªçèè´£æå¨ã
View
Viewå±åçå°±æ¯åUIç¸å ³çå·¥ä½ï¼æ们åªå¨XMLãActivityåFragmentåViewå±ç代ç ï¼Viewå±ä¸ååä¸å¡ç¸å ³çäºï¼ä¹å°±æ¯æ们å¨Activityä¸åä¸å¡é»è¾åä¸å¡æ°æ®ç¸å ³ç代ç ï¼æ´æ°UIéè¿æ°æ®ç»å®å®ç°ï¼å°½éå¨ViewModeléé¢å(æ´æ°ç»å®çæ°æ®æºå³å¯)ï¼Activityè¦åçäºå°±æ¯åå§åä¸äºæ§ä»¶(å¦æ§ä»¶çé¢è²ï¼æ·»å çåå²çº¿)ï¼Viewå±å¯ä»¥æä¾æ´æ°UIçæ¥å£(ä½æ¯æ们æ´å¾åææçUIå ç´ é½æ¯éè¿æ°æ®æ¥é©±å¨æ´æ¹UI)ï¼Viewå±å¯ä»¥å¤çäºä»¶(ä½æ¯æ们æ´å¸æUIäºä»¶éè¿Commandæ¥ç»å®)ãç®åå°è¯´ï¼Viewå±ä¸åä»»ä½ä¸å¡é»è¾ãä¸æ¶åæä½æ°æ®ãä¸å¤çæ°æ®ï¼UIåæ°æ®ä¸¥æ ¼çåå¼ã
ViewModel
ViewModelå±åçäºæ å好åViewå±ç¸åï¼ViewModelåªååä¸å¡é»è¾åä¸å¡æ°æ®ç¸å ³çäºï¼ä¸åä»»ä½åUIç¸å ³çäºæ ï¼ViewModel å±ä¸ä¼ææä»»ä½æ§ä»¶çå¼ç¨ï¼æ´ä¸ä¼å¨ViewModelä¸éè¿UIæ§ä»¶çå¼ç¨å»åæ´æ°UIçäºæ ãViewModelå°±æ¯ä¸æ³¨äºä¸å¡çé»è¾å¤çï¼åçäºæ ä¹é½åªæ¯å¯¹æ°æ®çæä½(è¿äºæ°æ®ç»å®å¨ç¸åºçæ§ä»¶ä¸ä¼èªå¨å»æ´æ¹UI)ãåæ¶DataBindingæ¡æ¶å·²ç»æ¯æååç»å®ï¼è®©æ们å¯ä»¥éè¿ååç»å®è·åViewå±åé¦ç»ViewModelå±çæ°æ®ï¼å¹¶å¯¹è¿äºæ°æ®ä¸è¿è¡æä½ãå ³äºå¯¹UIæ§ä»¶äºä»¶çå¤çï¼æ们ä¹å¸æè½æè¿äºäºä»¶å¤çç»å®å°æ§ä»¶ä¸ï¼å¹¶æè¿äºäºä»¶çå¤çç»ä¸åï¼ä¸ºæ¤æ们éè¿å¯¹ä¸äºå¸¸ç¨çäºä»¶åäºå°è£ ï¼æä¸ä¸ªä¸ªäºä»¶å°è£ æä¸ä¸ªä¸ªCommandï¼å¯¹äºæ¯ä¸ªäºä»¶æ们ç¨ä¸ä¸ªå»å¤çå°±è¡äºï¼ä¼æä½ å¯è½éè¦çæ°æ®å¸¦ç»ä½ ï¼è¿ä½¿å¾æ们å¨ViewModelå±å¤çäºä»¶çæ¶ååªéè¦å ³å¿å¤çæ°æ®å°±è¡äºï¼å ·ä½è§MVVM Light Toolkit 使ç¨æåç Command é¨åãå强è°ä¸éï¼ViewModel ä¸ååUIç¸å ³çäºã
Model
Modelå±æ大çç¹ç¹æ¯è¢«èµäºäºæ°æ®è·åçèè´£ï¼ä¸æ们平常Modelå±åªå®ä¹å®ä½å¯¹è±¡çè¡ä¸ºæªç¶ä¸åãå®ä¾ä¸ï¼æ°æ®çè·åãåå¨ãæ°æ®ç¶æååé½æ¯Modelå±çä»»å¡ãModelå æ¬å®ä½æ¨¡å(Bean)ãRetrofitçService ï¼è·åç½ç»æ°æ®æ¥å£ï¼æ¬å°åå¨(å¢å æ¹æ¥)æ¥å£ï¼æ°æ®ååçå¬çãModelæä¾æ°æ®è·åæ¥å£ä¾ViewModelè°ç¨ï¼ç»æ°æ®è½¬æ¢åæä½å¹¶æç»æ å°ç»å®å°Viewå±æ个UIå ç´ çå±æ§ä¸ã
å¦ä½åä½
å ³äºåä½ï¼æ们å æ¥çä¸é¢çä¸å¼ å¾ï¼
ä¸å¾åæ äºMVVMæ¡æ¶ä¸å个模åçèç³»åæ°æ®æµçèµ°åï¼æ们ä»æ¯ä¸ªæ¨¡åä¸ä¸æåæ¥çãé£ä¹æ们éç¹å°±æ¯ä¸é¢çä¸ä¸ªåä½ã
ViewModelä¸Viewçåä½ã
ViewModelä¸Modelçåä½ã
ViewModelä¸ViewModelçåä½ã
ViewModelä¸Viewçåä½
å¾2ä¸ViewModelåViewæ¯éè¿ç»å®çæ¹å¼è¿æ¥å¨ä¸èµ·çï¼ç»å®åæ两ç§ï¼ä¸ç§æ¯æ°æ®ç»å®ï¼ä¸ç§æ¯å½ä»¤ç»å®ãæ°æ®çç»å®DataBindingå·²ç»æä¾å¥½äºï¼ç®åå°å®ä¹ä¸äºå°±è½ææ°æ®åæ§ä»¶ç»å®å¨ä¸èµ·äº(å¦TextViewçtextå±æ§)ï¼ä½æ¯DataBindingæ¡æ¶æä¾çä¸å¤å ¨é¢ï¼æ¯å¦è¯´å¦ä½è®©ä¸ä¸ªURLç»å®å°ä¸ä¸ªImageViewï¼è®©è¿ä¸ªImageViewè½èªå¨å»å è½½urlæå®çå¾çï¼å¦ä½ææ°æ®æºåå¸å±æ¨¡æ¿ç»å®å°ä¸ä¸ªListViewï¼è®©ListViewå¯ä»¥ä¸éè¦å»åAdapteråViewHolderç¸å ³çä¸è¥¿?è¿äºå°±éè¦æ们åä¸äºå·¥ä½åç®åçå°è£ ãMVVM Light Toolkit å·²ç»å¸®æ们åäºä¸é¨åçå·¥ä½ï¼è¯¦æ å¯ä»¥æ¥çMVVM Light Toolkit 使ç¨æåãå ³äºäºä»¶ç»å®ä¹æ¯ä¸æ ·ï¼MVVM Light Toolkit åäºç®åçå°è£ ï¼å¯¹äºæ¯ä¸ªäºä»¶æ们ç¨ä¸ä¸ªå»å¤çå°±è¡äºï¼ä¼æå¯è½éè¦çæ°æ®å¸¦ç»ä½ ï¼è¿æ ·æ们å¤çäºä»¶çæ¶åä¹åªå ³å¿å¤çæ°æ®å°±è¡äºã
ç±å¾1ä¸ViewModelç模åä¸æ们å¯ä»¥çåºViewModelç±»ä¸é¢ä¸è¬å å«ä¸é¢5个é¨åï¼
Context (ä¸ä¸æ)
Model (æ°æ®æº Java Bean)
Data Field (æ°æ®ç»å®)
Command (å½ä»¤ç»å®)
Child ViewModel (åViewModel)
æ们å æ¥çä¸ç¤ºä¾ä»£ç ï¼ç¶ååä¸ä¸è®²è§£5个é¨åæ¯å¹²åç¨çï¼
// Activity context;//modelï¼æ°æ®æº Java Beanï¼private NewsService.News news;private .News topNews;//æ°æ®ç»å®ï¼ç»å®å°UIçå段ï¼data fieldï¼public final imageUrl = new ();public final html = new ();public final title = new ();// ä¸ä¸ªåéå å«äºææå ³äºView Style ç¸å ³çå段public final ViewStyle viewStyle = new ViewStyle();//å½ä»¤ç»å®ï¼commandï¼public finalonRefreshCommand = new ReplyCommand(() -> {
})public final ReplyCommand onLoadMoreCommand = new ReplyCommand((itemCount) -> {
});//Child ViewModelpublic final ObservableList itemViewModel = new ObservableArrayList();/** * ViewStyle å ³äºæ§ä»¶çä¸äºå±æ§åä¸å¡æ°æ®æ å ³çStyle å¯ä»¥åä¸ä¸ªå 裹ï¼è¿æ ·ä»£ç æ¯è¾ç¾è§ï¼
ViewModel 页é¢ä¹ä¸ä¼æ太å¤å¤ªæçå段ã **/public static class ViewStyle {
public final ObservableBoolean isRefreshing = new ObservableBoolean(true);
public final ObservableBoolean progressRefreshing = new ObservableBoolean(true);
}
Context
Android篇MVVM 到 MVI:迁移 Android 架构
迁移至 Model-View-Intent (MVI) 架构可能看似挑战重重,然而,其清晰的架构设计和预测性强的应用程序行为,使得这一转变显得尤为必要。
本文将深入解析 MVVM 与 MVI 之间的差异,并详细阐述如何实现 MVI 迁移。
MVVM 与 MVI
在移动应用开发领域,客服系统源码搭建MVVM 架构备受青睐。它通过将用户界面(View)与数据逻辑(ViewModel)分离,实现数据绑定的灵活应用。ViewModel 负责为 View 准备数据,并处理用户输入。
与之相比,MVI 架构作为近年来兴起的新模式,同样实现 View 与数据的分离。然而,它引入了名为 Intent 的新层,该层以结构化和可预测的方式表示用户操作,并将 Intent 传递给 Model。Model 根据Intent 产生新的状态,并在 View 中展示。
这两种架构的关键区别在于,在 MVVM 中,ViewModel 负责用户操作和更新 View 的状态。而在 MVI 中,Intent 作为独立的层,表示用户操作,使应用程序行为易于推断,同时便于处理边缘情况。
为什么选择 MVI?如何从 MVVM 迁移到 MVI?
从 MVVM 迁移至 MVI 虽然看似艰巨,实则是一个逐步的过程。以下是一些关键步骤:
步骤1:创建 Intent 类
步骤2:更新 ViewModel
步骤3:更新 Model
步骤4:更新 View
通过遵循上述步骤,您可以将现有的订阅功能源码 MVVM 架构逐步迁移至 MVI 架构,从而实现关注点分离、预测性强和可测试性高的应用程序。
androidui设计mvvm设计模式讨论?
讨论MVVM设计模式
在讨论中,参与者提到MVC和MVP在控制层的控制力上有显著差别。MVC模式在上世纪年代出现,经过三十多年的发展,演化出多种变种,包括MVP。然而,在Android开发中,Activity代码量庞大,往往需要承担过多职责,这主要是由于视图功能较弱导致。因此,有观点认为MVP优于MVC,它提供更强大的控制层,能最大程度上分担Activity中的逻辑工作。具体实现和详细思考可在相关博客中找到。
进一步,MVVM被视为MVP的升级版。在MVVM中,ViewModel结合了View的数据模型和Presenter的功能,通过Data Binding进行View和控制层间的交互,实现双向交互,降低耦合度,促进关注点分离,obd小程序源码减轻Activity的负担。在VM中,每个页面的数据模型只有一套,但Presenter应根据逻辑拆分。
相关资源推荐:Data Binding Guide、对MVC、MVP、MVVM的理解、Data Binding 用户指南(Android)
Android mvvm 之 databinding 原理
文本为原创内容,转载请注明出处——小舍
目录
1. Data Binding 的结构 [Top]
Data Binding 是在 Android 开发中体现 MVVM 架构思想的重要组件,其核心是观察者模式的实现。其功能主要集中在三个方面:
1.1 rebind 行为:Data Binding 通过将整个 Data 集合绑定到 View,实现数据的整体更新。例如,初始化和数据的整体更新可通过简单的赋值操作实现,由代理类 ViewDataBinding 完成。
1.2 observe data 行为:允许 View 观察 Data 的行为变化,仅更新需要的数据成员。通过将 Data 设置为 Observable,ViewDataBinding 作为代理观察者订阅 Data 的成员变化,实现精准的数据绑定。
1.3 observe view 行为:针对业务需求,实现 View 的单工和双工行为。单工View仅需 observe data 行为,而双工View则需同时实现 observe data 和 observe view 行为,以保证数据的一致性。
2. 样例分析——谷歌 sunflower 的改造 [Top]
sunflower app 是谷歌推荐的 jetpack 库应用的最佳实践,这里通过修改植物种植详情页面的实现,分析 observe view 行为。关键在于定义数据类 FakeData、布局文件 fragment_plant_detail.xml 和 ViewDataBinding 类 FragmentPlantDetailBinding。
2.1 Data——FakeData:定义了数据类 FakeData,包括两个成员。通过 observe data 行为,实现数据与 View 的精准绑定。
2.2 View——fragment_plant_detail.xml:布局文件中使用 @BindingAdapter 标注,实现数据与 View 节点的绑定。
2.3 ViewDataBinding——FragmentPlantDetailBinding:作为业务层的接口,实现读取 View 节点和 Data。结合观察者模式原理,实现数据到 View 的动态绑定。
3. 免 findViewById 的实现 [Top]
在暴露给业务层的 ViewDataBinding 类中,保存了布局文件中 View 节点的引用,通过观察者模式原理,实现免 findViewById 的动态绑定。主要流程包括读取 View 节点引用和数据成员引用两大部分。该文档参考的 androidx 版本为 core: 1.1.0。
Android-MVVM-Databinding的原理、用法与封装
Android-MVVM-Databinding,这个官方推荐的架构,尽管历经起落,但作为XML布局的主要解决方案,仍然具有其必要性。开发者们常常对它持有负面印象,认为它过时、更新缓慢且存在诸多缺点。然而,随着MVVM架构的流行,DataBinding作为其关键组件,学习和理解其原理、用法与封装变得至关重要。
传统 findViewById 方法存在性能问题,当布局复杂时,代码冗余且容易出错。DataBinding和ViewBinding的出现,旨在简化这一过程。ViewBinding甚至提供了编译时的空指针检查,而DataBinding则提供了双向绑定和XML变量等功能。尽管Kotlin-android-extensions曾让DataBinding在Kotlin项目中消失,但ViewBinding的出现让它重获关注。
使用DataBinding,无需手动导入依赖,只需配置后,XML布局可通过DataBindingLayout转换。变量和事件处理变得直观,比如双向绑定,使得UI与数据同步更为便捷。然而,实际开发中,还需注意如RV.Adapter中的使用、自定义View和属性处理等高级技巧,这些都有助于避免常见问题。
尽管DataBinding在某些场景下可能较为复杂,封装和优化可以简化常用操作。例如,Activity/Fragment主页面的封装,以及RV.Adapter的定制化。总的来说,DataBinding与MVVM的结合提供了更安全、更高效的UI管理,尽管未来可能被Compose取代,但在目前,掌握DataBinding仍是Android开发的必要技能。
学习建议包括理解双向绑定的优势,考虑同时使用ViewBinding以减少编译时的体积,以及注意性能优化,避免在XML中过多的逻辑处理。同时,关注BindingAdapter的使用,可以帮助简化数据绑定和监听设置。掌握DataBinding,对当前和未来的Android项目开发都大有裨益。
相关学习资源:[Android 学习链接]
听说这套框架可以搞定 Android MVI
前言
没有最完美的架构,只有最合适的架构。
Android应用架构变迁:MVC、MVP、MVVM、MVI。
关于这四种架构的概念、逻辑、实现方式与优劣,技术社区内优质文章不胜枚举,此处不再赘述。
今天重点介绍如何利用Airbnb开源框架Mavericks快速实践MVI架构。
主要弄清楚下面几个问题:
Mavericks(MvRx): Android on Autopilot
Mavericks是Aribnb开源的一款功能强大且易于学习的AndroidMVI框架。Mavericks以AndroidJetpack和KotlinCoroutines为基础搭建上层逻辑,在技术先进性和可持续方面毋庸置疑。至于框架实用性,相信接受了Airbnb、Tonal等大型APP长时间检验的Mavericks,不会让开发者失望。
核心概念
一个简单的计数界面只需要下面几行代码,既清晰又简洁。
实践
需求:利用WanAndroidAPI[1]实现搜索热词的列表展示(支持下拉刷新)
接口:/hotkey/json
1. 依赖2. 初始化
Application内onCreate()函数中执行初始化。
3. MavericksState
定义MainState并添加两个属性:
4. MavericksViewModel
定义MainViewModel管理MainState,实现获取搜索热词函数。
5. MavericksView
创建MainFragment并实现MavericksView接口用于展示搜索热词列表,用户可以下拉刷新请求新数据。
6. 效果源码
Talk is cheap,Show me the code。
/onlyloveyd/AndroidSamples
划重点
1. Async异步处理密封类,有四个子类:Uninitialized、Loading、Success、Fail,分别代表异步处理的4种状态。
2. onAsync异步属性状态变化监听
3. retainValue加载过程中或者加载失败后显示的数据。
示例中,我们将getHotKeys()函数内的retainValue去掉,界面更新数据时会有明显的闪动。
4. 监听模式:DeliveryMode
5. 状态监听防止崩溃
为了防止回调时界面已经被销毁而导致程序奔溃,采用launchWhenStarted防御策略。
总结
简单好用,是选轮子的基本标准。
上手Mavericks后,感觉代码层次清晰,集成方便,简单易用,符合好轮子的标准。
对于鄙人这种不太爱自己折腾框架的躺平者而言,简直福音。下一步准备把之前写的WanAndroidClient用Mavericks改写下。