ClassLoader与DexClassLoader简单例子

摘自:《Android 内核剖析》 作者:柯元旦
ClassLoader 类加载器,其作用是动态装载Class文件。每个ClassLoader在初始化时,必须指定Class文件的路径。
在一般情况下,应用程序不需要创建一个全新的ClassLoader对象,而是使用当前环境已经存在的ClassLoader。因为Java的Runtime环境在初始化时,其内部会创建一个ClassLoader对象用于加载Runtime所需的各种Java类。
每个ClassLoader必须有一个父ClassLoader,在装载Class文件时,子ClassLoader会先请求父ClassLoader 加载该文件,只有当其父ClassLoader找不到Class文件时,子ClassLoader才会继续装载该类,这事一种安全机制。

下面是我写的一个基于后面的DexClassLoader的例子,抽取出来的Java小例子:
IntelliJ IDEA 新建工程:PluginDemo
工程新建完毕,新建类PluginClass.java,代码如下:

public class PluginClass {
    public PluginClass() {
        System.out.println("plugin is init");
    }
    public int funtion(int a, int b) {
        return a + b;
    }
}

新建Demo.java类,代码如下:

public class Demo {
    public static void main(String[] args) {
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        try {
            Class<?> clazz = classLoader.loadClass("com.test.PluginClass");
            Object obj = clazz.newInstance();
            Class[] params = new Class[2];
            params[0] = Integer.TYPE;
            params[1] = Integer.TYPE;
            Method method = obj.getClass().getMethod("funtion", params);
            Integer integer = (Integer) method.invoke(obj, 12, 23);
            System.out.println("result: " +integer);
        } catch (Exception e) {
            e.printStackTrace();
        }    
    }
}

运行结果输出:
plugin is init
result: 35

DexClassLoader 是集成自 ClassLoader的一个类,集成关系如下:

java.lang.Object
   ↳    java.lang.ClassLoader
       ↳    dalvik.system.BaseDexClassLoader
           ↳    dalvik.system.DexClassLoader

Android 应用程序使用标准的Java编译器编译成Class文件,但最终的APK文件包含的确实dex文件类型。dex文件类型是将所需的所有的Class文件重新打包,优化后的一个新文件。因为要加载这样特殊的Class文件,所以就需要特殊的类装载器,这就是DexClassLoader。
下面是这本书里的DexClassLoader例子:

AndroidStudio新建工程Plugin:
新建类PluginClass,代码如下:

public class PluginClass {

    public PluginClass() {
        Log.e("tag", "Plugin Class initialized");
    }

    public int function(int a, int b) {
        return a + b;
    }
}

manifest中添加代码如下:

...
<activity android:name=".MainActivity">
     <intent-filter>
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
         <action android:name="com.n.plugin" />
      </intent-filter>
 </activity>
...

打好包,安装到手机(不用直接点击运行,这样后面跑宿主程序时,会抛找不到的异常)。

AndroidStudio新建工程Host:
MainActivity中添加代码如下:

private void addPlugin() {
        Intent intent = new Intent("com.n.plugin", null);
        PackageManager manager = getPackageManager();
        List<ResolveInfo> infoList = manager.queryIntentActivities(intent, 0);
        if (infoList.isEmpty()) {
            return;
        }
        ResolveInfo info = infoList.get(0);
        ActivityInfo activityInfo = info.activityInfo;

//      String div = System.getProperty("path.separator"); //多个文件路径之间的分隔符
        String packageName = activityInfo.packageName;
        String dexPath = activityInfo.applicationInfo.sourceDir;
        String dexOutputDir = getApplicationInfo().dataDir;
        String libPath = activityInfo.applicationInfo.nativeLibraryDir;

        DexClassLoader classLoader = new DexClassLoader(dexPath, dexOutputDir, libPath, getClass().getClassLoader());
        try {
//          获取Plugin中资源Id的方法
//          Resources res = manager.getResourcesForApplication(packageName);
//          int id = res.getIdentifier("version", "string", packageName);
//          String version = res.getString(id); 

            Class<?> clazz = classLoader.loadClass(packageName + ".PluginClass");
            Object obj = clazz.newInstance();
            Class[] params = new Class[2];
            params[0] = Integer.TYPE;
            params[1] = Integer.TYPE;
            Method method = clazz.getMethod("function", params);
            Integer integer = (Integer) method.invoke(obj, 12, 23);
            Log.e("tag", "--- 获取的结果是 --->" + integer);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

manifest中添加代码如下:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值