关于mvvm:MVI到底是不是凑数的通过案例与MVVM进行比较

前言最近看到不少介绍MVI架构,即Model-View-Intent的文章,有人留言说Google炒冷饭或者为了凑KPI“创造”了MVI这么一个词。和后端的敌人形容了一下,他们听了第一印象也是和MVVM如同区别不大。然而凭印象Google应该还没有到须要这样来凑数。 去看了一下官网,发现齐全没有提到MVI这个词。。然而举荐的架构图的确是更新了,用来演示MVI也的确很搭。 (官网图) 想了想,决定总结一下本人的发现,和掘友们一起探讨学习。 案例分享看过一些剖析MVI的文章,外面实现的办法各种各样,细节也不尽相同。甚至对于Model边界的划分也会不一样。 上面先分享一下在特定场景下我的MVVM和MVI实现(不重要的细节会省略)。 场景先预设一个场景,咱们的界面(View/Fragment)里有一个锅。次要工作就是实现一道菜的烹饪: flowchart LR停火 --> 热油 --> 加菜 --> 加调料 --> 出锅 几个须要留神的点: 初始状态:停火退出资料时:都是异步获取资料,再退出锅中完结状态:出锅本文次要是比拟MVVM和MVI,这里只分享这两种实现。 经典MVVM为了增强比照,这里的实现比拟靠近Android Architecture Components刚公布时官网的的代码架构和片段: (过后的官网图) // PotFragment.ktclass PotFragment { ... // 察看是否点火 viewModel.fireStatus.observe( viewLifecycleOwner, Observer { updateUi() if (fireOn) addOil() } ) // 察看油温 viewModel.oilTemp.observe( viewLifecycleOwner, Observer { updateUi() if (oilHot) addIngredients() } ) // 察看菜熟没熟 viewModel.ingredientsStatus.observe( viewLifecycleOwner, Observer { updateUi() if (ingredientsCooked) { // 加调料 addPowder(SALT) addPowder(SOY_SAUCE) } } ) // 察看油盐是否加完 viewModel.allPowderAdded.observe( viewLifecycleOwner, Observer { // 出锅! } ) viewModel.loading.observe( viewLifecycleOwner, Observer { if (loading) { // 颠勺 } else { // 放下锅 } } ) // 所有准备就绪,点火 turnOnFire() ...}// PotViewModel.ktclass PotViewModel(val repo: CookingRepository) { private val _fireStatus = MutableLiveData<FireStatus>() val fireStatus: LiveData<FireStatus> = _fireStatus private val _oilTemp = MutableLiveData<OilTemp>() val oilTemp: LiveData<OilTemp> = _oilTemp private val _ingredientsStatus = MutableLiveData<IngredientsStatus>() val ingredientsStatus: LiveData<IngredientsStatus> = _ingredientsStatus // 所有调料加好了才更新。这里Event外部会有flag提醒这个LiveData的更新是否被应用过 //(当年咱们还真用这种形式实现过单次生产的LiveData)。 private val _allPowderAdded = MutableLiveData<Event<Boolean>>() val allPowderAdded: LiveData<Event<Boolean>> = _allPowderAdded // 假如曾经实现逻辑从repo获取是否有还在进行的数据获取 private val _loading = MutableLiveData<Boolean>() val loading: LiveData<Boolean> = _loading fun turnOfFire() {} // 假如上面都是异步获取资料,这里简化一下代码 fun addOil() { repo.fetchOil() } fun addIngredients() { repo.fetchIngredients() } fun addPowder(val powderType: PowderType) { repo.fetchPowder(powderType) // 更新_allPowderAdded的逻辑会在这里 } ...}特点: ...

April 25, 2022 · 3 min · jiezi

关于mvvm:彻底理解Android架构重构Jetpack-MVVM

前言汇聚了业界出名架构文章。从建筑学的常识中失去一些对架构的思考,并以架构设计准则和目标对Jetpack MVVM 从新结构!github 后续本我的项目将继续更新,并欠缺 wanAndorid 的所有性能。还会用 23 种设计模式在我的项目中实际,彻底了解设计模式在业务场景中的应用,欢送关注 Github:https://github.com/blindmonk/WanArchitecture 一、什么是架构1.1 架构介绍架构到底是什么?如何更好的了解架构。咱们晓得中国文字博大精深能够说从文字的组成就能了解其含意。架构也不例外 “架构” 是由 “架” 、“构” 组成。 架:建造、搭设、撑持。简称:整体构造 构:屋宇、供人寓居的木、砖瓦构筑物。简称:组件整体构造和组件的组合就造成了架构。以 Android 架构为例子一个 APP 通常是有 class(类)组成,而这些 class 之间如何如何组合、相互之间如何产生作用,则是影响这个 APP 自身的关键点。细分的话能够分为类、接口(连接器)、工作流。所谓类就是组成架构的外围 “砖瓦”,而接口则是这些类之间通信的门路、通信的机制、通信的冀望后果。工作流则是形容零碎如何应用类和接口实现某一项需要比方:一次网络申请。下面介绍架构中提到了屋宇、木头、砖瓦可见架构和修建有着彼此的分割。 1.2 建筑学上世纪 60 年代曾经设计软件架构这个概念了,到了 90 年代软件架构这个概念才开始流行起来。而计算机的历史开始于上世纪五十年代相比修建历史就十分短暂了,建筑工程从石器时代就开始了。人类在几千年的建筑设计实际中积攒了大量的教训和教训,建筑设计基本上蕴含两点,一是建筑风格,二是修建模式。独特的建筑风格和失当抉择的修建模式,能够使它成为一个举世无双的修建。 下图的照片显示了现代玛雅修建:Chichen-Itza,九个微小的石级堆垒而上,九十一级台阶(象征着四季的天数)夺路而出,塔顶的神殿耸入云天。所有的数字都如日历般谨严,格调雄浑。难以想象这是石器时代的建筑物。 英国首相丘吉尔说,咱们结构建筑物,修建也结构咱们,英国下议院的会议厅较狭隘,无奈使所有的下议院议员面向同一个方向入座,而必须分成两侧入座。丘吉尔认为,议员们入座的时候天然会抉择与本人政见雷同的人同时入座,而这就是英国政党制的起源。 二、架构设计目标 简直所有的软件设计理念都能够在浩瀚的建筑学历史中找到。许多人认为 “模式必须遵从性能”(你认同这种观点吗?欢送在评论区留下你的认识)。而好的设计既有模式又有性能。比方咱们的北京大兴国内机场大兴机场以航站楼为外围向周围延展从地面鸟瞰就像是一只展翅欲飞的凤凰,以航站楼核心区为核心,别离向西南、西北、中南、东北、东南五个方向伸出了五条指廊,通往北京大兴国内机场的飞行区。这种从核心向五湖四海延长的设计,使航站楼中心点到最远端登机口的间隔只有 600 米左右,旅客步行返回最多只需 8 分钟。 修建的设计又有肯定的目的性,而软件架构设计也同理。软件架构目的性大抵可分为可扩展性、可定制化、可伸缩、可维护性: 1. 可扩展性: APP 必须可能在用户的 UV/PV 数量疾速减少的状况下,放弃软件正当的性能。只有这样在疾速的从 0 到 1 的需要迭代中能力后顾无忧。 2. 可定制化: 在同一个软件系统中可能面向的用户群体是不同的、多样的,须要满足依据用户群的不同和市场需求的不同进行定制化。比方一个 APP 中某些性能只针对特定用户凋谢。 3. 可伸缩性: 在新技术呈现的时候,一个软件系统该当容许接入新技术,从而对现有零碎进行性能和性能的扩大。 4. 可维护性: 软件系统的保护包含两方面,一是修复现有的 bug,二是将新的迭代需要开发到现有零碎中去。一个易于保护的零碎能够无效地升高人力和物力。 三、实际一个 APP:玩 Android 针对上面对架构的介绍,置信曾经从生疏走向相熟了。然而最重要的还是实际,平凡的毛主席已经说过 你要想晓得梨子的味道,就要亲口尝一下。因而借用了 wanAndoird 凋谢 API 简略实现一个 APP 并概括上述架构的关键点,次要的性能点如下: ...

March 4, 2022 · 2 min · jiezi

关于mvvm:使用-Source-Generators-快速编写-MVVM-代码

大家好,我是本期的微软 MVP 实验室研究员——陈锦华。微软 MVP ( Windows Development 方向),专一于 .NET 开发,有十多年的客户端开发教训。当初热衷于撰写博客,分享 WPF、UWP 和 Azure DevOps 相干的教训。 0.1. 对于 MVVM Toolkit.NET Community Toolkit 是以用于所有 .NET 开发人员的帮忙类和 API 的合集,并且与任何特定 UI 平台无关。 最它公布了 8.0.0 preview1 版本,它蕴含了从 Windows Community Toolkit 迁徙过去的以下组件: • CommunityToolkit.Common • CommunityToolkit.Mvvm • CommunityToolkit.Diagnostics • CommunityToolkit.HighPerformance 其中 CommunityToolkit.Mvvm 又名 MVVM Toolkit ,它是一个现代化、疾速以及模块化的 MVVM 库。它蕴含一个 Source Generators 组件:MVVM Toolkit source generators。这篇文章将介绍它如何帮忙开发着疾速编写 MVVM 代码。 0.2. MVVM Toolkit source generatorsSource Generators 是一项 C# 编译器性能,使 C# 开发人员可能在编译用户代码时进行查看,并动静生成新的 C# 源文件,以增加到用户的编译中。 通过这种形式,你的代码能够在编译过程中运行并查看你的程序以生成与其余代码一起编译的其余源文件。 对 MVVM 平台的开发者来说,Source Generators 是一个期待已久的新性能,毕竟 MVVM 模式中,开发者须要写很多命令和属性的额定的模板代码。到目前为止,为了加重这些额定代码的累赘,微软和其它开发者想出过很多不同的计划,而 Source Generators 看起来会是更好的一个。MVVM Toolkit 已开始了这方面的工作,8.0 版本又失去进一步的增强,当初 MVVM Toolkit source generators 是一个增量生成器,性能将会晋升很多。 上面将简略解说如何应用 MVVM Toolkit source generators 命令和属性的代码。 ...

February 16, 2022 · 2 min · jiezi

关于mvvm:WPF-DataTemplate与ControlTemplate结合使用

如深入浅出WPF中的形容,DataTemplate为数据的外衣,ControlTemplate为控件的外衣。ControlTemplate管制控件的款式,DataTemplate控制数据显示的款式,DataTemplate是ControlTemplate的一部分。本文介绍DataTemplate与ControlTemplate联合应用的办法,其关键在于ContentPresenter,它是DataTemplate的树根,代表DataTemplate的实例。 场景自定义Button,使其显示当前页与总页数,当页码变动时自动更新。 实现步骤自定义Button.ControlTemplate;自定义Button.ContentTemplate;创立数据类;创立ViewModel类;绑定。示例代码:// xaml<UserControl.Resources> <viewmodel:TextViewModel x:Key="TestViewModel"/></UserControl.Resources><Grid DataContext="{StaticResource TextViewModel}"> <Button Width="120" Height="50" Content="{Binding PageInfo}"> <Button.Template> <ControlTemplate TargetType="Button"> <ContentPresenter/> </ControlTemplate> </Button.Template> <Button.ContentTemplate> <DataTemplate> <TextBlock Width="{TemplateBinding Width}" TextAlignment="Center" FontSize="36" FontFamily="微软雅黑" Foreground="#ffffff"> <Run Text="{Binding CurrentPage}"/> <Run Text="/"/> <Run Text="{Binding TotalPages}"/> </TextBlock> </DataTemplate> </Button.ContentTemplate> </Button></Grid>// 数据类public class PageInfo : ViewModelBase{ public PageInfo(string currentPage, string totalPages) { this.CurrentPage = currentPage; this.TotalPages = totalPages; } public string CurrentPage { get { return currentPage; } set { currentPage = value; OnPropertyChanged("CurrentPage"); } } public string TotalPages { get { return totalPages; } set { totalPages = value; OnPropertyChanged("TotalPages"); } } private string currentPage; private string totalPages;}// viewmodel类public class TestViewModel : ViewModelBase{ public TextViewModel() { PageInfo = new PageInfo("1", "1"); } public PageInfo PageInfo { get { return pageInfo; } set { pageInfo = value; } } // 其它逻辑 private PageInfo pageInfo;}

February 24, 2021 · 1 min · jiezi