基于类加载DexClassLoader的“插件”结构
来源:互联网 发布:我的世界凋零风暴js 编辑:程序博客网 时间:2024/05/18 23:27
这篇文章主要讲类加载器在android中如何动态的加载其他工程类的过程,对于类加载器的知识就跳过了。
1、首先需要创建两个工程,我创建的工程是classloader和classloaderplugin,前面的工程是主工程,后面是插件。现在classloader工程需要调用classloaderplugin插件中的类中的方法。在这里使用反射就能解决此问题。
1.1 首先看下classloaderplugin中类的方法,很简单返回两个数的和。
public class PluginClass implements Comm{@Overridepublic int add(int a, int b) { return a+b;}}
1.2 创建类加载器和调用类里面的方法
这个com.test.lb.plugin.classloaderplugin过滤器(IntentFilter)是配置在classloaderplugin项目中的,通过它就可以获取手机上匹配的插件项目,这里就能获取classloaderplugin,继而可以该项目的包名,路径等。
private DexClassLoader createWrapperClassLoader(){try {//intent 过滤插件Intent intent = new Intent("com.test.lb.plugin.classloaderplugin",null);PackageManager pm = getPackageManager();final List<ResolveInfo> plugins = pm.queryIntentActivities(intent, 0);ResolveInfo rInfo = plugins.get(0);ActivityInfo activityInfo = rInfo.activityInfo;//String div = System.getProperty("path.separator");packageName = activityInfo.packageName;String dexPath = activityInfo.applicationInfo.sourceDir;String dexOutputDir = getApplicationInfo().dataDir;String libPath = activityInfo.applicationInfo.nativeLibraryDir;return new DexClassLoader(dexPath, dexOutputDir, libPath, this.getClass().getClassLoader());} catch (Exception e) {e.printStackTrace();}return null;}拿到类加载器cl之后,就可以加载类了,这里需要传入类的包名。通过newInstance创建一个对象,然后获取方法getMethod,第二个参数就是所调用方法的参数签名,最后通过invoke方法获取结果。运行时先要安装classloaderplugin即插件,然后在安装classloader主项目。
Class<?> clazz = cl.loadClass(packageName+".plugin.PluginClass");Object obj = clazz.newInstance();Class[] parameterTypes = new Class[2];parameterTypes[0] = Integer.TYPE;parameterTypes[1] = Integer.TYPE;Method method = clazz.getMethod("add", parameterTypes);tv_reflect_result.setText("反射调用: 20+30= "+method.invoke(obj, 20,30));
1.3 接口模型的“插件”
上面是通过反射调用方法来实现的,接着采用接口方法来实现。
首先创建一个接口,它位于classloader项目中,然后将改接口编译成一个jar包,在将这个jar包放到classloaderplugin中以library的形式添加到build path 中。接口定义如下:
public interface Comm {public int add(int a, int b);}创建类加载和1.2都是一样的,不同的事这次在newInstance时直接进行强制转换,Comm comm = (Comm) clazz.newInstance();直接转换成Comm接口,然后就直接调用里面的方法。
/** * 通过反射创建出对象然后将其强制转换成接口类型 */private void useDexClassLoaderIntf(){try {Class<?> clazz = cl.loadClass(packageName+".plugin.PluginClass");Comm comm = (Comm) clazz.newInstance();tv_result.setText("接口调用: 20+30= "+comm.add(20,30));} catch (Exception e) {e.printStackTrace();}}1.4 项目结构
1.5 基于上面的模式,写了一个简单的切换主题的效果
基本思路是,根据包名获取Resources对象,在通过类加载的创建一个对象并强制将其转换成颜色id的接口,在通过Resources的getColor方法获取颜色值。获取颜色的接口如下:第一个是背景色,第二个是文本的颜色,第三个是文本背景色。
public interface ColorIntf {public int getBackgroundColorId();public int getTextFontColorId();public int getTextBackgroundColorId();}在两个项目classloader和classloaderplugin中分别加入颜色值如:
<color name="background">#cdcdf5</color> <color name="textbackground">#FF55bb</color> <color name="text">#ccffaf</color>
<color name="background">#CDCDCD</color> <color name="textbackground">#FF5555</color> <color name="text">#000000</color>
在调用下面的方法给各个空间赋值,会根据传入不同的包名去加载不同的颜色实现类。
private void useDexClassLoaderColorIntf(String packagename){try {Class<?> clazz = cl.loadClass(packagename+".plugin.ColorClass");ColorIntf colorIntf = (ColorIntf) clazz.newInstance();Resources resources = readResources(packagename);tv_result.setTextColor(resources.getColor(colorIntf.getTextFontColorId()));tv_result.setBackgroundColor(resources.getColor(colorIntf.getTextBackgroundColorId()));ll_main.setBackgroundColor(resources.getColor(colorIntf.getBackgroundColorId()));tv_reflect_result.setTextColor(resources.getColor(colorIntf.getTextFontColorId()));tv_reflect_result.setBackgroundColor(resources.getColor(colorIntf.getTextBackgroundColorId()));} catch (Exception e) {e.printStackTrace();}}
1.6 最后效果图
下载地址
- 基于类加载DexClassLoader的“插件”结构
- 【Android高级】DexClassloader和PathClassloader动态加载插件的实现
- Android插件化探索(一)类加载器DexClassLoader
- Android插件化探索(一)类加载器DexClassLoader
- Android插件化探索(一)类加载器DexClassLoader
- android基于类装载器DexClassloader设计“插件框架”
- android基于类装载器DexClassloader设计“插件框架”
- android基于类装载器DexClassloader设计“插件框架”
- android基于类装载器DexClassloader设计“插件框架”
- android基于类装载器DexClassloader设计“插件框架”
- android基于类装载器DexClassloader设计“插件框架”
- Android 程序插件框架基于DexClassLoader
- 类加载器(DexClassLoader)与插件化(动态加载)
- java通过映射动态加载类 android的DexClassLoader
- DexClassLoader 插件
- DexClassLoader和PathClassLoader类加载机制
- Android类加载之PathClassLoader和DexClassLoader
- Android插件化开发之用DexClassLoader加载未安装的APK资源文件来实现app切换背景皮肤
- 北京软件开发-java技术注意事项
- Servlet生成验证码在JSP页面显示,单击验证码图片可刷新
- 多个UIPickerView切换(纯代码)
- 毕业设计-基于JAVAEE的B2B2C网上商城-中遇到的问题
- Android视图消息传递
- 基于类加载DexClassLoader的“插件”结构
- maven学习笔记-02-maven配置篇
- django函数HttpResponse
- ubuntu11.10下编译openwrt的环境配置
- 创建及删除索引
- RTSP协议分析-3
- UVA - 818 Cutting Chains 暴力
- Windows下搭建x64 PHP的开发测试环境
- 剑指offer-4 替换空格