11.22 java,android,classLoder,插件式开发,类的热替换,android热更新原理

来源:互联网 发布:淘宝提高信誉度 编辑:程序博客网 时间:2024/04/29 21:34

android插件原理:
http://www.cnblogs.com/over140/archive/2011/11/23/2259367.html
http://get.ftqq.com/987.get

主要需要将studio生成的jar转化成android可以使用的jar(dex):
 dx –dex –output=test.jar dynamic.jar
如果插件在加载时报错:
Class ref in pre-verified class resolved to unexpected implementation
说明你的jar包含接口类,这是classloder不允许的,所以出现这个错误

转载请注明出处:http://blog.csdn.net/u010499721

这篇文章简述了部分原理,以及提及开发插件中可能会遇到的问题
http://www.trinea.cn/android/android-plugin/
其中一句话:


(2) AndroidDynamicLoader GitHub:https://github.com/mmin18/AndroidDynamicLoader
这是点评一个工程师介绍的方式,和上面不同的是:他不是用代理 Activity 的方式实现而是用 Fragment 以及 schema 的方式实现


本人详细的看了一下点评开源插件的代码,上面提及的schema的技术中,需要用到它的原因是:
插件开发需要加载资源(不能加载资源图片布局之类的都是用处不大的插件技术),如果直接使用eclipse的导出java包功能,就会出现:
android.content.res.Resources NotFoundException
这个问题,原因是用eclipse导出的jar包确实没有android的R文件,所以点评的工程师写了个anttasks的工具,用ant的自定义打包生成apk,还附带发布功能(怀疑点评内部一直在使用)

开发插件过程成,可能会出现重复的类,一个在应用程式里面,一个在插件jar里面,此时涉及到一个classloder的隔离问题,简单的说就是classloder一般都会优先加载父类的class,如果找不到,在从当前classloder里面加载,其实也可以自定义classloder加载重复的内,本人亲自尝试,发现find处理的总是空(求懂的大神指导)。

插件开发过程中还有可能需要加载lib依赖库,可以通过重写classloder实现。具体看点评开源插件的MyClassLoder类。

在设计插件开发的app过程中,有尝试找到一些可以替换重复的class的自定义classloder方法,以下有两篇不错的文章:
1.http://blog.csdn.net/z69183787/article/details/29234905
2.(IBM JAVA类热替换)http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/index.html

可以把类在运行的时候替换掉?让我想起spring的方法(getter,setter赋值控制)注入,估计原理就是这个。

android 热更新的原理:

一篇不错的文章:
http://blog.csdn.net/lzyzsd/article/details/49843581

原理:
classloder的findclass方法会从dexElements加载dex文件,加载的class实际是加载dex文件里面的内容,热更新这些class只需要反射修改dexElements指向的文件。

public Class findClass(String name, List<Throwable> suppressed) {    for (Element element : dexElements) {        DexFile dex = element.dexFile;        if (dex != null) {            Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);            if (clazz != null) {                return clazz;            }        }    }    if (dexElementsSuppressedExceptions != null) {        suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));    }    return null;}

修改方法:

private static synchronized Boolean injectAboveEqualApiLevel14(            String dexPath, String defaultDexOptPath, String nativeLibPath, String dummyClassName) {    Log.i(TAG, "--> injectAboveEqualApiLevel14");    PathClassLoader pathClassLoader = (PathClassLoader) DexInjector.class.getClassLoader();    DexClassLoader dexClassLoader = new DexClassLoader(dexPath, defaultDexOptPath, nativeLibPath, pathClassLoader);    try {        dexClassLoader.loadClass(dummyClassName);        Object dexElements = combineArray(                getDexElements(getPathList(pathClassLoader)),                getDexElements(getPathList(dexClassLoader)));        Object pathList = getPathList(pathClassLoader);        setField(pathList, pathList.getClass(), "dexElements", dexElements);    } catch (Throwable e) {        e.printStackTrace();        return false;    }    Log.i(TAG, "<-- injectAboveEqualApiLevel14 End.");    return true;}

demo:
https://github.com/lzyzsd/AndroidHotFixExamples
demo备份:https://github.com/qq179157977/AndroidHotFixExamples

到最后,我想说,不要搞什么插件开发了,那是eclipse年代的东西,现在用studio应该搞热更新,app下载一次,更新无限次都可以,搞插件开发反而身心劳累~

0 0
原创粉丝点击