关于Android如何动态加载res

最近抽时间看了一下android插件化的东西。

也稍微研究了一下。总结一下权当记录。

同时也把研究过程中的testbed上传到github了,造福后人吧。

####为什么需要插件化?

最简单的原因大概就是为了避免过大的体积(rom size),以加速下载和安装。

更多的原因例如插件化后可以单独升级避免每次一个小改动就app体量的升级,为了针对不同区域不同用户做不同的适配,为了市场更高的单app评分(插件的差评不算主app中)等等。

####哪些可以插件化?

大部分的功能性代码/资源及非自定义的布局

####可用插件化方案: 这里仅讨论:以apk(在插件化的前提下,相比较jar,apk要灵活的多)的形式插件化的方案。

这里不讨论:自行定义数据格式,并自行实现解析器(parser或LayoutInflater)的方案。(因为造这种轮子总让我想起曾经一个叫XXUI的垃圾框架。。。)


综上,要加载插件化的资源/函数/activity等,对于已安装的apk可以用aidl,intent等各种系统提供的“普遍”方法;未安装的apk就是用反射去先获取到Resource和Asset等Context,再加载。

个人认为,不管apk是安装还是不安装,都不建议单独插件化布局(毕竟涉及界面交互(如点击/回调等),设置个listener都很麻烦)。

而对于涉及界面交互的插件(其实算功能),建议使用“直接启动activity”的方式。

Start activity虽然会造成界面跳转之间的闪烁和卡顿,但是相比较生硬的反射,不管是从实现复杂度还是从代码可维护性上来说,都是利大于弊的;更不用说用了反射(依赖name),代码混淆就比较尴尬了。 (BTW,Android设计activity的初衷,就是作为一个自治单元)

另外目前也有一些成型的插件化框架可以直接使用,如

http://www.apkplug.com/

https://github.com/singwhatiwanna/dynamic-load-apk

另外注意一点,上面的code必须要有卡读写权限(其实文档建议是最好别放外部存储上):

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

差不多就这些了~ 有遗漏和更新再补充。


本文参考了各位前人的经验(排名不分先后):

@Siddharth Naik

Load resource (layout) from another apk dynamically

@singwhatiwanna

DL : Apk动态加载框架@Github

APK动态加载框架(DL)解析

Android apk动态加载机制的研究

@tabolt

获取未安装资源apk种的资源文件

@jefferyyangkai

qq游戏大厅中解析不安装apk的研究