一、前言

在 插件化知识梳理(6) - Small 源码分析之 Hook 原理 这一章的学习完成之后,下一步我们将进入插件化加载的精髓,动态加载类的学习,在此之前,我们需要先准备一些关于类加载的知识。

Android当中,支持动态加载的两种方式为:DexClassLoaderPathClassLoader。这两者之间的区别为:

  • DexClassLoader
  • 可以加载jar、apk、dex
  • 支持从SD卡目录加载。
  • PathClassLoader
  • 在许多文章中都有提到,在Dalvik虚拟机上,只能加载已经安装到系统中的Apk文件,也就是/data/app目录下的apk文件。之所以有这个限制是因为PathClassLoader会去读取data/dalvik-cache目录下经过优化后的dex文件,如果文件不存在,那么就会报错。由于手边没有机器,所以没有版本验证。
  • 而在ART虚拟机上,通过源码当中的注释,可以发现是支持的。

二、具体实例

实例的工程目录结构为:

  • app:宿主模块
  • library:插件模块
  • libraryinterface:插件接口模块

其中,applibrary模块分别依赖于libraryinterfacelibrarylibraryinterfaceAndroid Library类型的Module,下面,我们开始讲解整个工程的构建过程。

2.1 接口模块 libraryinterface

接口模块相当于是宿主模块和插件模块所定义的一套标准,宿主模块遵循固定的业务逻辑,而具体的实现则根据插件模块的不同而不同。 在接口模块中,我们定义一个简单的接口IPlugin.java

public interface IPlugin {public int getVersion();
}
复制代码

2.2 插件模块 library

首先,我们在插件模块的build.gradle文件中,引入libraryinterface模块

dependencies {//引入接口模块compile project (':libraryinterface')
}
复制代码

接着,我们编写一个实现类:

public class PluginImpl implements IPlugin {@Overridepublic int getVersion() {return 1;}
}
复制代码

接下来需要做的就是将该插件模块打包成一个jar文件,同样是在build.gradle文件中,创建一个Task任务:

task makeJar(type: Copy) {delete 'build/libs/plugin.jar'from ('build/intermediates/bundles/release/')into ('../file/')include ('classes.jar')rename ('classes.jar','plugin.jar')
}makeJar.dependsOn(build)
复制代码

首先点击make module

接下来,在项目的根目录下执行命令:

./gradlew makeJar
复制代码

就会得到一个plugin.jar文件,但是这个jar文件是不能够被动态加载的,因为它内部其实是.class文件,我们通过解压可以看出:

那么我们就需要通过Android SDK自带的dx工具进行转换,把它转换为.dex,转换后的文件为plugin_dex.jar

/Users/lizejun/Library/Android/sdk/build-tools/25.0.3/dx --dex --output=file/plugin_dex.jar file/plugin.jar
复制代码

plugin_dex.jar解压之后,可以看到它已经被转换成了.dex文件:

最后,将该jarpush到手机中的/sdcard/Plugin目录下:

2.3 宿主模块 app

首先,宿主模块同样需要依赖于接口模块libraryinterface

dependencies {//引入接口模块compile project (':libraryinterface')
}
复制代码

在代码当中,我们通过DexClassLoader/PathClassLoader动态外部的插件plugin_dex.jar,通过反射实例化PluginImpl类,并调用它的getVersion()方法进行验证:

public class MainActivity extends AppCompatActivity {private TextView mTextView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTextView = (TextView) findViewById(R.id.tv_plug_result);getPluginA();}private void getPluginA() {File dexOutputDir = getDir("dex1", 0);String dexPath = Environment.getExternalStorageDirectory().toString() + "/Plugin/plugin_dex.jar";DexClassLoader loader = new DexClassLoader(dexPath, dexOutputDir.getAbsolutePath(), null, getClassLoader());try {Class clz = loader.loadClass("com.demo.lizejun.library.PluginImpl");IPlugin impl = (IPlugin) clz.newInstance();int version = impl.getVersion();mTextView.setText("Version=" + version);} catch (Exception e) {e.printStackTrace();}}private void getPluginB() {String dexPath = Environment.getExternalStorageDirectory().toString() + "/Plugin/plugin_dex.jar";PathClassLoader loader = new PathClassLoader(dexPath, getClassLoader());try {Class clz = loader.loadClass("com.demo.lizejun.library.PluginImpl");IPlugin impl = (IPlugin) clz.newInstance();int version = impl.getVersion();mTextView.setText("Version=" + version);} catch (Exception e) {e.printStackTrace();}}}
复制代码

最终的结果为:


更多文章,欢迎访问我的 Android 知识梳理系列:

  • Android 知识梳理目录:www.jianshu.com/p/fd82d1899…
  • 个人主页:lizejun.cn
  • 个人知识总结目录:lizejun.cn/categories/

插件化知识梳理(7) 类的动态加载入门相关推荐

  1. Android插件化开发基础之App如何动态加载类

    在 Java 里面,我们可以把一些类放到 .jar 文件里面,然后用 ClassLoader 动态加载.例如: URLClassLoader ucl = URLClassLoader.newInsta ...

  2. 【Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  3. java 自定义classloader_编写自定义classloader实现类的动态加载

    目标:实现类的动态加载 原理:使用java的自定义classloader机制实现类的动态加载. 代码实现://自定义classloader public class StrategyClassLoad ...

  4. 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图...

    如果你使用过一些开源CMS的话,肯定会用过其中的的插件化功能,用户可以通过启用或者上传插件包的方式动态添加一些功能,那么在ASP.NET Core MVC中如何实现插件化开发呢,下面我们来探究一下. ...

  5. 利用反射实现类的动态加载

    为什么80%的码农都做不了架构师?>>>    //首先定义一个接口来隔离类: public interface Operator { // public java.util.Lis ...

  6. java动态加载类 框架_java运用RMI框架类的动态加载不成功

    最近在看<java网络编程精解>,第11章中用RMI动态加载类,可怎么试都不成功,求大神解答 1. 我先在C盘下启动了rmiregistry注册表,如果部署成功注册表应该会从codebas ...

  7. JAVA反射机制、Class类及动态加载、成员变量构造方法其他方法的反射与调用、代理模式AOP

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调用对象的方法的功能称为java语言 ...

  8. 动态加载、插件化、热部署、热修复(更新)知识汇总

    开发中经常能听到动态加载,插件化,热部署等词,动态加载到底是何方神物,它能实现什么功能,实现原理又如何?动态加载和插件化.热部署又有着什么样的联系呢?下面我们一起来学习吧. 1. 基本知识 1.1 动 ...

  9. Android插件化开发之动态加载技术系列索引

    动态加载介绍 在Android开发中采用动态加载技术,可以达到不安装新的APK就升级APP功能的目的,可以用来到达快速发版的目的,也可以用来修复一些紧急BUG. 现在使用得比较广泛的动态加载技术的核心 ...

最新文章

  1. 力扣(LeetCode):字符串转换整数 (atoi)
  2. 大一java实训报告1500字_社会实践报告1500字
  3. C#中在定义事件委托时怎样跨窗体传递参数
  4. python进程池pool_python多任务--进程池Pool
  5. 83.删除排序链表中的重复元素(力扣leetcode) 博主可答疑该问题
  6. 国稻种芯百团计划行动 胡培松:早稻可以向用途多元化发展
  7. excel工作表合并
  8. 自主导航:赋予移动机器人智能感知与运动的能力
  9. apktool java_apktool 是GOOGLE提供的APK编译工具,需要JAVA运行环境,推荐使用JDK1.6或者JDK1.7...
  10. linux gbk 语言包安装,linux 安装gbk字符集
  11. 失败一时并不可怕,可怕的是不去总结和改正。
  12. 高考首日,为梦想加油!
  13. unittest之TestSuite类详解
  14. 文件共享服务器onedrive,如何共享OneDrive文件和文件夹
  15. 12c oracle 01109,Oracle 12c redo 丢失恢复
  16. Tomb.Finance的每周更新(5.9-5.15)
  17. Azure 开发者新闻快讯丨开发者6月大事记一览
  18. 软件测试黑马程序员课后答案_软件测试课后参考答案
  19. httpPrinter--vue--打印
  20. Gitblit搭建及Git协作开发流程

热门文章

  1. windows7 64位机上配置支持GPU版(CUDA7.5)的OpenCV2.4.13操作步骤
  2. 【OpenCV】将图像数据由YUV格式转换成JPG格式直接使用,而不保存成文件
  3. redis mysql排行榜实现_redis实现排行榜
  4. Java学习总结:40(国际化)
  5. oracle存储空间管理,Oracle存储空间管理
  6. 争吵所达到的效果要_悟空:不要害怕争吵,有时候争吵一些不喜欢的事情也能创造和谐...
  7. 【java】兴唐第二十三节课作业
  8. 连接 linux服务器
  9. 第五次作业:四则运算之升级
  10. 41-高级路由:BGP AS长度:接收一切、最大AS长度、不比较AS长度