Android 插件开发,做成动态加载
为什么需要插件开发:
相信你对Android方法数不能超过65K的限制应该有所耳闻,随着应用程序功能不断的丰富,总有一天你会遇到一个异常:
Conversion to Dalvik format failed:Unable toexecute dex: method ID not in [0, 0xffff]: 65536
可能有些同学会说,解决这个问题很简单,我们只需要在Project.proterty中配置一句话就Ok啦,
dex.force.jumbo=true
是的,加入了这句话,确实可以让你的应用通过编译,但是在一些2.3系统的机器上很容易出现
INSTALL_FAILED_DEXOPT异常
对于以上两个异常,我们先来分析一下原因:
1、Android系统中,一个Dex文件中存储方法id用的是short类型数据,所以导致你的dex中方法不能超过65k
2、在2.3系统之前,虚拟机内存只分配了5M
知道了原因,我们就来一个个的解决上面的问题,首先对于65k的问题,我们在应用层是无法改变android系统的结构的,所以我们无法将数据类型从short改变为int或者其他类型,也就是说一个dex中的方法数不能超过65k是我们无法逾越的鸿沟,我们只能减少一个dex中的方法数,首先最容易想到的方案就是去掉一些无用的Jar包,以及将一些属性设置为public,从而可以去掉get/set方法,这种方法只能临时解决问题,随着时间的推移,总有一天还是会出现方法数超过65k的,毕竟一个应用一般是在加功能,不会减功能。
解决方案:
(1)将一些功能做成插件,动态加载。
(2)分包方案,将一个apk中的dex文件分割成多个dex文件,然后动态的去加载dex文件。
其实这两种方案的核心思想是一样的,插件是把未来要开发的新功能做成apk和dex动态加载,而分包方案是将已经完成的功能分成多个dex文件动态加载,其实我个人觉得插件方案比分包方案更好的解决了65k的问题,因为插件方案不仅能够解决65k问题,还能让我们的应用体积减小,而分包只能解决65k的问题。
如何开发插件,进行动态加载:
研究文章Android 动态加载 Apk (Activity) :Android apk 动态加载机制的研究 Android apk 动态加载机制的研究(二):资源管理和Activity声明周期管理
实现Android 动态加载 Apk (Fragment) 实现
插件apk的开发规范
文章开头提到,要想成为一个插件apk,是要满足一定条件的,如下是采用本文机制开发插件apk所需要遵循的规范:
1. 不能用this:因为this指向的是当前对象,即apk中的activity,但是由于activity已经不是常规意义上的activity,所以this是没有意义的。
2. 使用that:既然this不能用,那就用that,that是apk中activity的基类BaseActivity中的一个成员,它在apk安装运行的时候指向this,而在未安装的时候指向宿主程序中的代理activity,anyway,that is better than this。
3. 不能直接调用activity的成员方法:而必须通过that去调用,由于that的动态分配特性,通过that去调用activity的成员方法,在apk安装以后仍然可以正常运行。
4. 启动新activity的约束:启动外部activity不受限制,启动apk内部的activity有限制,首先由于apk中的activity没注册,所以不支持隐式调用,其次必须通过BaseActivity中定义的新方法startActivityByProxy和startActivityForResultByProxy,还有就是不支持LaunchMode。
5. 目前暂不支持Service、BroadcastReceiver等需要注册才能使用的组件。
注意:动态加载的apk不能和宿主应用包含相同的jar包,不然会报错。