2024年业务架构的救世主是 MVI(一)_android mvi 开源架构(2),2024年最新嵌入式软件工程师面试题

学习分享,共勉

Android高级架构师进阶之路

题外话,我在阿里工作多年,深知技术改革和创新的方向,Android开发以其美观、快速、高效、开放等优势迅速俘获人心,但很多Android兴趣爱好者所需的进阶学习资料确实不太系统,完整。今天我把我搜集和整理的这份学习资料分享给有需要的人

  • Android进阶知识体系学习脑图

  • Android进阶高级工程师学习全套手册

  • 对标Android阿里P7,年薪50w+学习视频

  • 大厂内部Android高频面试题,以及面试经历

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

这样设计的另一个好处是当专注于一层协议时,其余层的技术细节可以不予关注,同一时间只需要关注有限的复杂度,比如传输层不需要知道自己传输的是 HTTP 还是 FTP,传输层只需要专注于端到端的传输方式,是建立连接,还是无连接。

有限复杂度的另一面是“下层的可重用性”。当应用层的协议从 HTTP 换成 FTP 时,其下层的内容不需要做任何更改。

引子

该系列的前三篇结合“搜索”这个业务场景,讲述了不使用架构写业务代码会产生的痛点:

  1. 低内聚高耦合的绘制:控件的绘制逻辑散落在各处,散落在各种 Activity 的子程序中(子程序间相互耦合),分散在现在和将来的逻辑中。这样的设计增加了界面刷新的复杂度,导致代码难以理解、容易改出 Bug、难排查问题、无法复用。
  2. 耦合的非粘性通信:Activity 和 Fragment 通过获取对方引用并互调方法的方式完成通信。这种通信方式使得 Fragment 和 Activity 耦合,从而降低了界面的复用度。并且没有一种内建的机制来轻松的实现粘性通信。
  3. 上帝类:所有细节都在界面被铺开。比如数据存取,网络访问这些和界面无关的细节都在 Activity 被铺开。导致 Activity 代码不单纯、高耦合、代码量大、复杂度高、变化源不单一、改动影响范围大。
  4. 界面 & 业务:界面展示和业务逻辑耦合在一起。“界面该长什么样?”和“哪些事件会触发界面重绘?”这两个独立的变化源没有做到关注点分离。导致 Activity 代码不单纯、高耦合、代码量大、复杂度高、变化源不单一、改动影响范围大、易改出 Bug、界面和业务无法单独被复用。

详细分析过程可以点击下面的链接:

  1. 写业务不用架构会怎么样?(一)
  2. 写业务不用架构会怎么样?(二)
  3. 写业务不用架构会怎么样?(三)

紧接着又用了三篇讲述了如何使用 MVP 架构对该业务场景的重构过程。MVP 的确解决了一些问题,但也引入了新问题:

  1. 分层:MVP 最大的贡献在于将界面绘制与业务逻辑分层,前者是 MVP 中的 V(View),后者是 MVP 中的 P(Presenter)。分层实现了业务逻辑和界面绘制的解耦,让各自更加单纯,降低了代码复杂度。
  2. 面向接口通信:MVP 将业务和界面分层之后,各层之间就需要通信。通信通过接口实现,接口把做什么和怎么做分离,使得关注点分离成为可能:接口的持有者只关心做什么,而怎么做留给接口的实现者关心。界面通过业务接口向 Presenter 发出请求以触发业务逻辑,这使得它不需要关心业务逻辑的实现细节。Presenter 通过 view 层接口返回响应以指导界面刷新,这使得它不需要关心界面绘制的细节。
  3. 有限的解耦:因为 View 层接口的存在,迫使 Presenter 得了解该把哪个数据塞给哪个 View 层接口。这是一种耦合,Presenter 和这个具体的 View 层接口耦合,较难复用于其他业务。
  4. 有限内聚的界面绘制:MVP 并未向界面提供唯一 Model,而是将描述一个完整界面的 Model 分散在若干 View 层接口回调中。这使得界面的绘制无法内聚到一点,增加了界面绘制逻辑维护的复杂度。
  5. 困难重重的复用:理论上,界面和业务分层之后,各自都更加单纯,为复用提供了可能性。但不管是业务接口的复用,还是View层接口的复用都相当别扭。
  6. Presenter 与界面共存亡:这个特性使得 MVP 无法应对横竖屏切换的场景。
  7. 无内建跨界面(粘性)通信机制:MVP 无法优雅地实现跨界面通信,也未内建粘性通信机制,得借助第三方库实现。
  8. 生命周期不友好:MVP 并未内建生命周期管理机制,易造成内存泄漏、crash、资源浪费。

详细分析过程可以点击下面的链接:

  1. MVP 架构最终审判 —— MVP 解决了哪些痛点,又引入了哪些坑?(一)
  2. MVP 架构最终审判 —— MVP 解决了哪些痛点,又引入了哪些坑?(二)
  3. MVP 架构最终审判 —— MVP 解决了哪些痛点,又引入了哪些坑?(三)

再然后用了两篇讲述了 MVVM 架构是如何解决 MVP 的痛点:

  1. ViewModel 的引入使得“有免死金牌的业务层”成为可能,也使得跨界面之间的业务逻辑共享以及通信变得轻松。
  2. LiveData 的引入使得业务层成为数据持有者以数据驱动刷新界面,还避免了生命周期问题以及内存泄漏风险。
  3. 因为数据持有者,MVVM 也引入了新的复杂度,首先是不好处理的粘性数据问题,更棘手是更新数据的方法是带有副作用的,由此会引发界面状态不一致问题。

关于 MVVM 架构的详细分析可以点击下面的链接:

  1. “无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(一)
  2. “无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(二)

从这一篇开始,试着引入 MVI 架构的思想进行搜索业务场景的重构,看看是否能解决上述痛点。

在重构之前,再介绍下搜索的业务场景,业务流程如下:在搜索条中输入关键词并同步展示联想词,点联想词跳转搜索结果页,若无匹配结果则展示推荐流,返回时搜索历史以标签形式横向铺开。点击历史可直接发起搜索跳转到结果页。

将搜索业务场景的界面做了如下设计:

搜索页用Activity来承载,它被分成两个部分,头部是常驻在 Activity 的搜索条。下面的“搜索体”用Fragment承载,它可能出现三种状态 1.搜索历史页 2.搜索联想页 3.搜索结果页。

Fragment 之间的切换采用 Jetpack 的Navigation。关于 Navigation 详细的介绍可以点击Navigation 组件使用入门 | Android 开发者 | Android Developers

MVP & MVVM & MVI 架构图比对

MVI 和 MVP/MVVM 不是非此即彼的关系,它们是不同维度的。

MVP 和 MVVM 关心的是业务层的形态,MVP 中业务层用 Presenter 表达,如下图所示:

而 MVVM 中业务层用 ViewModel 表达,如下图所示:

MVI 不关心业务层形态,而是关心业务数据变换及流动的形态。

将名词解释放在一边,先来看看架构图表达形式上的差异。

MVI 的图和其他两个相比有一个显著的区别,之前使用的是{},比如View{Presenter{}}表示 View 持有一个 Presenter。但 MVI 的架构图中使用的是(),表示一个函数,即 Model 是 Intent 的函数,View 是 Model 的函数。

函数 & 函数式编程

函数即两个集合之间的一种对应关系。若对集合 x 中的值施加法则 f 后都能唯一对应集合 y 中的一个值,则说 y 是 x 的函数,记为y = f(x)

这里的关键是唯一自变量 x 对应唯一应变量 y。在数学中这是简单的一元函数,在编程中这是一种低复杂度,低复杂度意味着不会出错。

把一元函数进一步具象化到界面刷新这个 case 上,可以表达为 “一个 Model 唯一对应一个界面状态”,记为view = f(model)

按照这个思想回看一下 MVVM 架构中的函数关系(同样的问题也存在于 MVP 中),界面的状态有若干个LiveData<Model>表达,即 viewState = f(model1, model2, model3, …),其中任何一个 model 都可以独立发生变化,而任一 model 变化后,都会引起 viewState 的变化,即所有 model 的任一排列组合与一个 viewState 对应。这个复杂度就很高,出错的概率就很大,这样的错误称为界面状态不一致,即界面状态和你预想的不一样,因为有一种排列组合没有考虑到。关于实战中界面状态不一致的实例分析可以点击“无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(一)

MVI 把函数对应关系做到了极致,它把界面刷新的整个流程都表达成了一元函数。首先界面发起的动作被抽象为数据 Intent,Intent 的函数是 Model,即model = f1(intent),表示任一业务动作会产生唯一对应的 model,紧接着任一 Model 对应唯一界面状态,即view = f2(model)

f1 和 f2 这两个一元函数描述了业务意图、数据、界面状态之间一一对应的关系,在需求文档确定下来的同时,这一一对应的关系就已固定下来。

将函数的思想应用到编程,就产生了函数式编程

函数式编程是一种编程范式,即关于如何编写程序的方法论。它的主要思想是把运算过程尽量写成一系列嵌套的函数调用。

这种编程范式最大的好处是没有副作用。副作用是指函数内部与外部互动,产生运算以外的其他结果。最典型的情况是修改全局变量。关于 MVVM 中的副作用详解可以点击“无架构”和“MVP”都救不了业务代码,MVVM能力挽狂澜?(二)

而函数式编程中只有输入参数和返回值,不修改全局变量。从耦合的角度来看,函数式编程中的函数只包含运算且不与任何东西耦合,这使得它复杂度低、运行结果可预测、易于单元测试、调试。函数式编程是 MVI 架构相较于其他架构的一个显著不同点。

综上,使用 MVI 架构的开发过程即是:

运用函数式编程思想将需求翻译成业务意图(I)、数据(M)、界面状态(V)间的函数关系,再用响应式编程的方式将其串联成数据流的过程。

最后将函数串联的方式是响应式编程。它是一种面向数据流的编程范式。关于响应式编程的详细介绍可以点击Android 架构之 MVI 雏形 | 响应式编程 + 单向数据流 + 唯一可信数据源

除了编程范式上之外,MVI 架构还有一些其他的不同点,引用之前文章的总结:

MVI = 响应式编程 + 单向数据流 + 唯一可信数据源

关于这三条规范的剖析可以点击该系列文章:

  1. Android 架构之 MVI 雏形 | 响应式编程 + 单向数据流 + 唯一可信数据源
  2. Android 架构之 MVI 初级体 | Flow 替换 LiveData 重构数据链路
  3. Android 架构之 MVI 完全体 | 重新审视 MVVM 之殇,PartialChange & Reducer 来拯救
  4. Android 架构之 MVI 究极体 | 状态和事件分道扬镳,粘性不再是问题

其中的响应式编程会运用 Kotlin Flow,关于它的详细介绍可以点击:

  1. Kotlin 异步 | Flow 应用场景及原理
  2. Kotlin 异步 | Flow 限流的应用场景及原理

总结

在具体分析 MVI 的实现细节之前,对其做一个概念性总结:

最后

简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。

选定你想去的几家公司后,先去一些小的公司练练,学习下面试技巧,总结下,也算是熟悉下面试氛围,平时和同事或者产品PK时可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!

面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。

金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值