转自:http://blog.csdn.net/czh0766/article/details/6736826
最近突发奇想,想做一个插件框架,就是实现一个微内核,所有扩展功能都通过下载插件加载的方式来实现,原理跟现在用的eclipse差不多。要做到这些动态加载类少不了,就是内核上事先定义好接口,通过网络或其他方式下载的插件要实现这些接口,只要定义好规则,系统就可以使用这些插件了。
Android动态加载不是程序本身的类,要用到PathClassLoader和DexClassLoader, 两个类的构造方法分别是:
- PathClassLoader(String path, ClassLoader parent);
- DexClassLoader(String dexPath, String dexOutputDir, String libPath, ClassLoader parent);
- DexClassLoader loader = new DexClassLoader("/sdcard/dog.apk", "/sdcard", null, ClassLoader.getSystemClassLoader());
- Class<?> clazz = loader.loadClass("czh.plugin.Dog");
- Animal dog = (Animal)clazz.newInstance();
- dog.sayHello();
查看了Class类forName(String name)方法的源代码,发现它们加载类用的不是ClassLoader.getSystemClassLoader(), 而是VMStack.getCallingClassLoader(), 于是俺把代码改了一番,终于运行通过了:
- DexClassLoader loader = new DexClassLoader("/sdcard/dog.apk", "/sdcard", null, VMStack.getCallingClassLoader());
Java的ClassLoader其实是一个链式结构,加载类的时候优先从最顶层的ClassLoader开始加载,若无法找到该类才尝试下一级ClassLoader加载。上述代码保证了类Animal能被VMStack.getCallingClassLoader()加载,类Dog被loader加载,同时这两个类在同一个ClassLoader加载链中,确保了它们的父子关系能正常识别,这样就不会发生ClassCastException异常了。
不过VMStack这个类被标识为deprecated, 将来可能被google去除不给我们使用,到时候就要想些方法来克服这点困难了。