当前位置: 首页 > 科技观察

吃透Android架构

时间:2023-03-18 14:25:10 科技观察

前言本文实现一个wanAndroid项目,有理论知识和架构原理,全部用kotlin编写,舍弃Rxjava,因为kotlin完全可以替代他,github这个项目总结了业界知名的架构文章和一些项目帮助您彻底理解架构。未来本项目将持续更新完善wanAndorid的各项功能。我也会在项目中使用23种设计模式进行实践,深入理解设计模式在业务场景中的使用。欢迎继续关注github:更多信息可在文末查看。一、什么是架构1.1架构简介架构到底是什么?如何更好地理解架构。我们知道汉字博大精深。可以说从字的构成就可以理解意思。建筑也不例外。“建筑”由“框架”和“结构”组成。框架:建立、建立、支持。简称:整体结构结构:供人居住的房屋、木结构、砖瓦结构。简称:组件的整体结构和组件的组合构成架构。以Android架构为例,一个APP通常是由类组成的,而这些类如何组合、如何交互是影响APP本身的关键点。如果再细分的话,可以分为类、接口(连接器)、任务流。所谓类就是结构的核心“砖头”,而接口就是这些类之间通信的路径、通信的机制、通信的预期结果。任务流是描述系统如何使用类和接口来完成某个需求,例如网络请求。在上面的建筑介绍中,提到了房子、木头、砖瓦。可见,建筑与建筑物是相互关联的。1.2架构软件架构的概念是在1960年代设计出来的,直到1990年代软件架构的概念才开始流行起来。计算机的历史始于1950年代,与始于石器时代的建筑史相比,这一历史非常短暂。人类在几千年的建筑设计实践中积累了大量的经验和教训。建筑设计基本上包括两点,一是建筑风格,二是建筑模型。独特的建筑风格和正确选择的建筑模式可以使其成为一种独一无二的建筑。下图是玛雅古建筑:奇琴伊察,九个巨大的石阶堆叠起来,九十一级台阶(象征着四季的天数)奔涌而出,塔顶的神庙耸入云霄.所有的数字都像日历一样严谨,气势磅礴。很难想象这是一座石器时代的建筑。英国首相温斯顿丘吉尔说,我们建造建筑物,建筑物建造我们。英国下议院的议事厅比较狭窄,所有下议院议员不可能坐在同一个方向,而必须坐在两侧。丘吉尔认为,议会议员就座时,自然会选择与自己政见相同的人同时就座,这就是英国政党制度的由来。2.架构设计目的几乎所有的软件设计理念都可以在浩瀚的架构史中找到。很多人认为“形式必须服从功能”(你同意这个观点吗?欢迎在评论区留下你的看法)。好的设计兼具形式和功能。比如我们北京大兴国际机场大兴机场就是以航站楼为核心,向四面八方延伸。从空中看,它就像一只展翅的凤凰。以航站楼核心区为中心,分别向东北、东南、中南、西南延伸。5条走廊向西北方向五个方向延伸,直达北京大兴国际机场飞行区。这种由中心向四面八方延伸的设计,使得航站楼中心到最远登机口的距离只有600米左右,旅客步行仅需8分钟。建筑的设计有一定的目的性,软件架构的设计也是如此。软件架构的目的大致可以分为可扩展性、定制化、可扩展性和可维护性:可扩展性:APP必须能够在用户UV/PV数量快速增加的情况下保持软件合理的性能。只有这样,才能从0需求快速迭代到1需求,无后顾之忧。可定制:同一个软件系统可能针对不同的、多样化的用户群体,需要根据不同的用户群体和市场需求进行定制。例如,APP中的某些功能仅对特定用户可用。可扩展性:当新技术出现时,软件系统应该允许接入新技术,以扩展现有系统的功能和性能。可维护性:一个软件系统的维护包括两个方面,一是修复已有的bug,二是在已有系统中开发新的迭代需求。易于维护的系统可以有效地减少人力和物力。3、实践一个APP:玩转Android基于上面对架构的介绍,相信已经由陌生变成了熟悉。但最重要的是练习。伟大的毛主席曾说过,要想知道梨的滋味,必须亲自尝一尝。所以利用wanAndoird开放的API简单实现一个APP,总结一下以上架构的要点。主要功能如下:首页是热搜文章分类列表。项目页面主要包括完整的项目文章。单击项目以查看详细信息。上面说的印象就是上面说的“形式必须服从功能”。当然,这不是权威定义,可以作为参考。不管是formfollowsfunction还是functionfollowsform,我们都可以用结构化思维来理解这句话。建筑大致可以分为:形式和功能。所以我们依次根据这两点来构建wanAndroid工程。3.1架构——形式形式本身由两部分组成。一是事物的外部形态,二是内部结构与组合。其实两者是一样的。内容如何对内结合,对外自然会有一定的表现形式。打开项目首先看到的是我们项目的目录结构。更清晰简洁的目录结构可以帮助我们更快的上手项目。主要分为核心模块和业务功能模块两部分:核心模块主要有以下职责:Dagger依赖注入处理。扩展功能:各种实用程序。基础层抽象:BaseActivity、BaseViewModel等三库处理、网络异常处理等业务功能模块,主要有以下好处:高内聚,功能结构清晰模块化功能隔离封装在主APP下,用于核心和特性划分,业务模块不是以模块化的形式划分成多个模块,而是聚合在特性下,以包的形式聚合。这样做的好处是:更快的编译速度减少了maven库的依赖冲突通用功能包内聚的重要性可见我们没有采用按照业务模块的模块化划分,因为我一直在接触之前有一个项目,拆分了40多个模块。可想而知,一旦项目变大,劣势就会暴露出来:编译一个项目最多需要7/8分钟。编译速度优化可以参考我之前的文章(编译速度优化)。项目中的模块依赖于交叉。当然,我并不反对多模块模块化的存在,因为任何模式都有优点和缺点。使用哪种形式取决于当前项目的业务。另外,所有项目都是用kotlin写的:build.gradle.kts.kts也是官方推荐的,可以让gradle更加简化。这些功能点大部分都离不开网络请求和回调处理。这里我不再描述MVC、MVP、MVVM的区别和如何选择,但我可以说明没有最好的或最优的架构模型,只有最适合当前业务的才是好的架构。现在Google官方推荐的架构主要是MVVM,所以我们主要讲MVVM。更多细节请参考官网文档。应用架构指南:MVVM架构模式满足了我们上面描述的架构设计的目的,也符合官方的架构原则。大致有以下两种架构原则。光看这两个定义可能不太容易理解。我们用结构化思维的方式理解,关注点分离就是把复杂的问题进行合理的分解,然后研究分解的各个方面,最后综合出一个整体的解决方案。所以,我们不应该在Activity或者Fragment里面做业务逻辑,而是把功能点拆分成要求最小的最优方案,最后合并成一个整体的方案。例如,在mvvm中,我们派生了ViewModel、LiveData、Model等。关注点分离你的Activity或Fragment中的代码应该是处理UI和OS交互的逻辑。尽可能保持这些类精简,这样可以避免许多与生命周期相关的问题。通过模型驱动接口模型是负责操作应用程序数据的组件。它们独立于应用程序中的View对象和应用程序组件,因此不受应用程序生命周期和相关关注点的影响。MVVM中的每个组件只依赖于它的下层组件如:activity-->viewMoudle-->Repository。这时候,你可能会有疑惑。如果是单向依赖,如何处理网络请求的回调?这里提出一个“响应式编程”的概念,结合liveData进行处理。它的内部是观察者模式,关联视图如:Activity、Fragment或Service的语句循环。使用LiveData的好处如下:无内存泄漏Observers绑定到Lifecycle对象,并在其关联的生命周期被销毁后进行清理。不会因Activity停止而崩溃如果观察者的生命周期处于非活动状态(例如后台堆栈中的Activity),它将不会收到任何LiveData事件。不再需要手动处理生命周期UI组件只是观察相关数据,不会停止或继续观察。LiveData将自动管理所有这些操作,因为它会在观察到相关生命周期状态变化时意识到这一点。3.3UseCaseUseCase是Clean架构中的一个概念,主要用于UI与数据层的连接,也用于IO切换。这里可以看到这个项目放弃了Rxjava,因为它可以被Kotlin取代。abstractclassUseCasewhereType:Any{abstractsuspendfunrun(params:Params):Either{operatorfuninvoke(params:Params,onResult:(Either)->Unit={}){valjob=GlobalScope.async(Dispatchers.IO){run(params)}GlobalScope.launch(Dispatchers.Main){onResult(job.await())}}classNone}3.4一个完整的网络请求流程查看:发送和订阅一个网络请求,来处理UI数据。ViewModel:为View(Activity/Fragment)提供数据,处理业务逻辑。LiveData:具有可观察生命周期的数据存储类,LiveData存储在ViewModel中UseCases:用于连接ViewModel和Model,更新LiveData。模型:数据可以从网络、数据库或其他API获取。4.总结我们可以体验一下从架构理论定义到实践的过程。相信大家有自己的理解和感悟,但这只是一种实现方式。如果你在满足架构设计的目的和架构原则的情况下,有更好的实践或者对架构项目有什么疑惑,欢迎在评论区或Github留言讨论。我在这里也有一个问题。你同意形式必须服从功能吗?欢迎留下你的意见。未来本项目将持续更新完善wanAndorid的各项功能。我也会在项目中使用23种设计模式进行实践,深入理解设计模式在业务场景中的使用。欢迎继续关注。其他平台如后端、前端架构搭建时,都是朝着同一个目标去的。但我还是有几点建议:业务决定架构,不要过度设计,面向接口编程,形式服从功能