You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
android-notes/blogs/Android/口水话/项目总结.md

4.4 KiB

项目总结相关口水话

目录

  1. 组件化 + MVP
  2. 项目中遇到哪些问题,是怎么解决的?

项目架构

我们项目采用的是组件化 + MVP。

模块化大家都知道,new 一个 App Module 即可,组件化不过是模块化更细粒度的表现。我们项目的大致架构是:

/** 此处该有张图 **/

组件化需要解决两个问题,业务模块的划分以及组件间的通信。业务模块的划分是比较麻烦的,因为之前写的都耦合在了一起,目前我们也只有一个发票的模块独立拆分了出来。组件间的通信可以采用 ARouter。ARouter 的源码我倒是没有看过,不过之前也写过路由跳转,核心的思想就是生成一个 Map,Path 对 Activity 的映射。实现方式有两种,第一种是通过元数据的形式,即在 Manifest 注册 Activity 时添加 meta-data 信息,然后在 Application 的 onCreate 时去扫描所有的 Activity 生成 Map,这种方式实现简单,几十行代码就能写完了。第二种方式则是比较传统的通过编译时注解 + JavaPoet 的形式,和 ButterKnife 原理一样。但是写的时候还是发现一些问题的,注解处理器在每个模块下都要引入,生成的类的全限定名是当前的包名 + 类名,里面就一个 public static 的方法,方法里面就是写好的 HashMap 一系列的 put 方法,接下来就是要每个模块生成的 Map 进行合成即可,但是问题来了,在 app 模块是不知道其他模块的名字呀,于是只能在 assets 目录下配一个 json 文件用来读取每个模块的模块名,有了模块名就有了前面生成的类的全限定名了,然后反射执行方法合成 Map 即可。

接下来就说说 MVP,MVP 相对于 MVC 来说,完全解耦了 View 层和 Model 层。主流的实现方式是以 Activity 作为 View 层,Presenter 层负责网络请求和数据处理,然后把处理后的数据以接口回调的方式传给 View 显示。

然后,就没了

遇到哪些问题,是如何解决的?

输出项目里的权限信息

这个在 Gradle Plugin 口水话里面讲过,就不多说了。

getGlobalVisibleRect

有一个需求是需要判断一个 TextView 在屏幕内是否可见,然后我就网上搜了一下,发现有一个 getGlobalVisibleRect 这个 Api,它返回的是一个 boolean 值,看了一下文档,可以传一个 Rect 作为参数,之后会拿可见区域的信息给这个 Rect 赋值。起初我是用这个返回值直接判断的,但是后面测试反馈说有 bug,我这测试也没啥问题呀。琢磨了半天才发现,原来顶层布局是一个 ScrollView,ScrollView 会把所有的子 View 一下子全都加载进来,所以这个 getGlobalVisibleRect 会一直返回 true。解决办法就是拿 Rect 的 top 去和屏幕的高判断,如果大于屏幕的高,就说明不在屏幕内,然后测试反馈说有一个小屏手机还是有问题。我去一看,稍微滑动一点,TextView 就显示出来了,我打印了 Rect 的信息,发现真的巧合,它的高度刚好比屏幕的高度高 1 个像素,但是由于 TextView 本身有上边距的影响,导致实际上不可见,然后判断的时候加个 10 像素就行了。

构建优化

测试有一次反馈打包好慢呀,我试了一下,我们打 debug 包耗时半分钟左右,但是测试在 Jenkins 打 debug 包却接近了两分钟。没得办法,搞一下,之前也参加过 DroidCon 和携程、有赞的关于编译优化的技术分享,拿出来实践一下。最后呢,成果是全量编译由之前的 1m 59s 到 1m 1s,代码增量编译由之前的 27s 到 9s,资源增量由之前的 8s 到 10s。除了资源的逆优化,其他优化效果都非常明显。

Gradle 的执行分为三大阶段:Initialization -> Configuration -> Execution 阶段。Initialization 阶段主要目的是初始化构建,它分为两个子过程,一个执行 Init Script,另一个执行 Setting Script。Init Script 会读取全局脚本初始化一些通用的属性,比如 Gradle User Home 目录、Gradle version 等。Setting Script 更常见,它初始化一次构建所参与的所有模块。Configuration 阶段主要影响全量构建的时间,而 Execution 阶段则主要影响增量构建的时间。

具体优化措施我在 Gradle 口水话中已经说了,我就不多哔哔了。