谈谈这么个设计---Android插件式开发

插件式开发是什么,有什么优缺点,测试有什么注意点,这个今天就来谈一谈。

在开始前先来复习一下基础知识

反射

反射,在程序运行的时候才根据名字去动态加载类,方法,相比于import的方式,不需要在编译的时候就必须知道,而是运行的时候一个动态的过程,因此,具有非常好的灵活性。

.dex文件

这是安卓的二进制文件,java最终输出是.class或者.jar,而android则是对许许多的.class进行优化,最终形成.dex,这个文件也是本文中最重要的东西

DexClassLoader

我们知道java默认的是ClassLoader,是用来加载类文件的,加载Dex文件用什么呢,当然是google给我们开发的DexClassLoader啦,它的继承关系如下:
这里写图片描述

loadclass的过程

    protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
        Class<?> clazz = findLoadedClass(className);

        if (clazz == null) {
            ClassNotFoundException suppressed = null;
            try {
                clazz = parent.loadClass(className, false);
            } catch (ClassNotFoundException e) {
                suppressed = e;
            }

            if (clazz == null) {
                try {
                    clazz = findClass(className);
                } catch (ClassNotFoundException e) {
                    e.addSuppressed(suppressed);
                    throw e;
                }
            }
        }

        return clazz;
    }

于是解释是这样的,
1.传入你要load的类名
2.去已加载的类看下有没有已经加载了的,有就直接返回
3.没有去父类的classloader查找有没有加载
4.还是没有,通过findclass去正真加载你的自定义类

好了,基础就这么多,下面说说好处,其实就是两个字,灵活。
那么对应于商业应用来说有两点优势:

第一点,按需下载,比如QQ的主题,打包整个主题资源显然不合适,所以按用户需要自己去下载,然后动态反射加载这些主题功能。

第二点,无痕更新,一个安装包发出去了,就收不回来了,修复BUG只能等待下一次更新,但是有了插件就不一样了,把重点模块的逻辑以插件dex的形式存放,有BUG,马上修,马上推送,用户甚至不用退出应用,只需要一次返回,就完成更新了,非常爽快。

缺点:好像没发现影响很大的缺点,汗…

ok,回到测试当中来,其实在我看来loadclass这个过程完全是交给系统做的,所以本身没有什么BUG,但是我们要注意的地方是load周边逻辑,包括:
怎么比对插件新旧版本 新旧插件交替的过程中旧的插件处理,新的插件有没有正确加载 新旧apk版本有没有正确使用对应的dex插件

主要测试方式还是通过log的形式展现,其二就是通过load目录对应的md5值判断

最后,来一段实现的不太规范的小小demo:
插件实现了抽象类,调用的时候只需要反射加载代码并转为定义的抽象类,这样就可以直接调用方法了,有点多态的味道。

package com.cloudhuan.dexloader;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Display;

import dalvik.system.DexClassLoader;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Mock_Dex mock_dex = new Mock_Dex();
        DexClassLoader dexClassLoader = new DexClassLoader(mock_dex.getDexPath(),this.getDir("tmp_dex", 0).toString(),null,this.getParent().getClassLoader());
        try {
            Class clazz =  dexClassLoader.loadClass("com.cloudhuan.plugin");
            MyRun myRun = (MyRun) clazz.newInstance();
            myRun.run();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

class Mock_Dex{
    String dexPath;
    public String getDexPath(){
        return dexPath;
    }
}

abstract class MyRun{
        public abstract void run();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值