作者:郑文
首先我们并不在讨论车牌号..但在2016年依然讨论multidex是一个图样图森破的问题,本文尽量避免谈论重复的技术点,只探讨一下multidex提供给我们的技术启示。
multidex技术原理可以分成两个部分:
在app启动时,通过Multidex.install api,扩展ClassLoader的dexElements数组来存储所有dex,这个流程会根据android sdk版本的不同做不同的处理,整个流程完全通过反射完成。
编译过程中的分包机制,将app中的class以某种方式将class分布在多个dex中
从multidex的原理,很容易想起目前比较流行的一个代码热修复方案策略。安卓App热补丁动态修复技术介绍 ,qzone的技术思路在社区诞生了很多技术框架,其中知名度最高的就是Nuwa。但客观的说,nuwa这个项目是完全达不到产品release的要求。在调研完所有同技术路线开源框架后,我们决定造个能应用在线上产品的轮子。
MultiDex机制的出现本身是为了避免出现app 65535问题的出现,但随着业务逻辑的增长,以及不合理的模块划分,导致main dex的方法数也超出了65535,这就导致了main dex capacity exceeded异常。
同时,Multidex的接入额外还会对app的启动性能造成影响。Multidex在install时需要加载dex,首次启动时还需要做odex的转换,而这些都是在ui主线程中完成。 根据 Carlos Sessa的测试,启用multidex后,4.4或以下的设备,app的启动时间平均会增加15%的时间,更严重的情况,甚至在启动时候会出现了黑屏。
目前部分app采取的策略是,放弃掉Multidex的,而转为插件化的架构。通过将非核心模块的lazy load,来达到启动速度的优化,但我们需要明确的是,并不是所有app都似乎插件化架构,为了实现启动加速或热更新将本耦合的业务逻辑硬生生拆解才是本末倒置。
在Android的性能优化中,最常见的思路就是异步化,减少UI线程的工作。在应用的交互层面上,app启动时,几乎所有app都会有一个SplashActivity。在界面上展示欢迎页,在后台进行初始化的业务逻辑。这就给我们一个启发,我们可以将系统的初始化逻辑,延迟到我们的业务初始化时间点上。
更加具体的方式是,我们可以将Multidex.install异步化,保证主线程的正常进行,待加载完成后通知SplashActivity跳转到真正的业务主界面。
在MultiDex加载的异步化之后,我们可以进行第二步:main dex大小的精简。
Multidex会在入口Application的attachBaseContext,加载second dex,因此multidex分包的基本原则是:保证app启动需要的class放置在main dex上。在gradle 1.5以上,multidex通过CreateManifestKeepList和MutidexTransform完成,分包过程可以分为三步:
CreateManifestKeepList会解析出AndroidManifest.xml中所有的组件类:包括Activity、Service、Receiver以及ContentProvider,这些类将会和Application入口类一起放在build/intermediates/multi-dex/{flavor}/{buildType}/manifest_keep.txt中
MutidexTransform会查找manifest_keep.txt中所有类的直接引用类,具体的方式是遍历类的所有字段类以及方法,查看方法的参数和返回值的类型,将其放保存在maindexlist.txt
将maindexlist.txt文件包含的所有class编译进main dex
从上面的分析中,我们可以确定的是,MultiDex的分包机制并不严密:
基于这两个缺陷,我们决定对MultiDex的分包流程进行优化:
首先通过替换掉manifest_keep.txt,去除不相关的组件,只保证入口需要的相关class
在gradle中添加extenstion扩展块,通过简单的属性设置即可在main dex中添加被multidex遗漏的class,而不需要手工编写task
额外需要提的一个细节是,dx工具的minimal-main-dex参数
这个参数可以保证只有被–main-dex-list文件中指定的类被打包在第一个dex,其余的都在第二个dex文件中,但在gradle1.5之后,这个参数被默认关闭的,因此我们在gradle插件中通过挂载javaagent的方式对dx过程进行了hook,保证我们的main dex精简化效果。
网易云大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经作者郑文授权发布。