android 插件化

组件化
将一个app分成多个模块,每个模块都是一个组件(Module),这些组件相互依赖或者单独调试部分组件等,但最终发布的是将这些组件合并统一成一个apk。
android工程组件:
lib组件和application组件
application组件
是指该组件本身就可以运行并打包成apk
lib组件
是指该组件属于app的一部分,可以供其它组件使用但是本身不能打包成apk
应用场景:
稍微改动一个模块的一点代码都要编译整个工程,耗时耗力
公共资源、业务、模块混在一起耦合度太高
不方便测试
组件化优点:
1、每个模块可以独立开发编译运行
2、开发单个模块时可以共享资源和工具类
3、可以针对单个模块测试

插件化
开发时将整个app拆分成很多模块,这些模块包括一个宿主和多个插件,每个模块都是一个apk(组件化的每个模块是个lib),最终打包的时候将宿主apk和插件apk分开或者联合打包
应用情景:
一种是插件与宿主apk没有交互,只是在用户使用到的时候进行一次交互,
一种是与宿主有很多的交互。
插件化优点:
1、宿主和插件分开编译、编译速度更快
2、模块解耦
3、解除单个dex函数不能超过 65535的限制
4、动态升级(动态更新插件)、按需下载模块、下载更新特别省流量,应用程序非常容易扩展
5、并发开发、开发高效高
缺点:
1、增加了主应用程序的逻辑难度
2、技术有难度,目前一些成熟的框架都是闭源的

动态加载
又叫热加载或动态部署,指容器(App)在运行状态下动态加载某个模块,从而新增功能或改变某部分行为

热修复
更新的类或者插件粒度较小的时候,一般用于修复bug
热更新(2016 Google的Android Studio推出了Instant Run功能)同时提出了3个名词:
“热部署”
方法内的简单修改,无需重启app和Activity。
“暖部署”
app无需重启,但是activity需要重启,比如资源的修改。
“冷部署”
app需要重启,比如继承关系的改变或方法的签名变化等。

插件包格式:
一种是apk
一种是dex包
插件的接入机制:
一种是需要安装
一种是不需要安装
结合插件包的格式来说插件的方式只有三种:
1、apk安装
2、apk不安装
3、dex包
(三种方式其实主要是解决两个方面的问题:1、加载插件中的类,2、加载插件中的资源)

DexOpt
它的执行过程是在第一次加载Dex文件的时候进行的,它对Dex进行优化,生成一个ODEX(Optimised Dex–ODex的执行效率会比直接执行Dex文件的效率要高很多)文件。

DexOpt会对每一个类的方法id进行检索,并存在一个链表结构里面,但链表的长度是用一个short类型来保存的,导致了方法id的数目不能够超过65536个(新版本Android系统中,DexOpt修复了该问题)。当一个项目足够大的时候,显然这个方法数的上限是不够的。

为了对低版本的Android系统做兼容,解决方法数超限的问题,需要将该dex文件拆成两个或多个,为此谷歌官方推出了multidex兼容包,配合AndroidStudio实现了一个 APK包含多个dex的功能

davilk和art虚拟机:
ART模式相比原来的Dalvik,会在安装APK的时候,使用Android系统自带的dex2oat工具把APK里面的dex文件转化成OAT文件

资源加载:
资源id
是在编译时生成的,其生成的规则是0xPPTTNNNN,
PP段:
是用来标记apk的,默认情况下系统资源PP是01,应用程序的PP是07。
TT段:
是用来标记资源类型的,比如图标、布局等,相同的类型TT值相同,但是同一个TT值不代表同一种资源,如这次编译的时候可能使用03作为layout的TT,那下次编译的时候可能会使用06作为TT的值,具体使用那个值,实际上和当前APP使用的资源类型的个数是相关联的。
NNNN:
则是某种资源类型的资源id,默认从1开始,依次累加。
1、
将编译时的TT值固定,即可是资源id达到分组的效果、避免重复。如将宿主程序的layout资源的TT固定为33,将插件程序资源的layout的TT值固定为03(也可不对插件程序的资源id做任何处理,使其使用编译出来的原生的值), 即可解决资源id重复问题。
固定资源id的TT值:提供一份public.xml,在public.xml中指定什么资源类型以什么TT值开头即可
2、
通过定制过的aapt在编译时指定插件的PP段的值来实现分组,重写过的aapt指定PP段来实现id分组:
重写 Context 的getResource()、getAsset()之类的方法。资源冲突需要扩展aapt实现。
打包后执行一个脚本修改资源ID。

代码加载:
classloader加载dex,代理模式就是本身宿主中有Activity,通过欺骗系统来创建Activity,欺骗系统的部分hook的有深有浅(对比DroidPlugin和Small),让这个Activity有生命周期,而动态加载模式就是运行时动态创建并编译一个Activity类,需要使用动态创建类的工具实现动态字节码操作。
1、简单加载模式。
2、Activity代理模式。
3、动态加载模式