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

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下载一次,更新无限次都可以,搞插件开发反而身心劳累~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值