插件化

作者: 34sir | 来源:发表于2018-07-30 09:57 被阅读6次

    作用

    • 宿主和插件分开编译 编译时只需要编译宿主 插件是在编译完成之后下发到宿主的
    • 并发开发 宿主发布版本不受插件影响 只需要提供一个入口给插件
    • 动态更新插件
    • 按需下载模块
    • 65536

    与组件化的区别

    • 组件化将app拆分成多个模块 开发过程中相互依赖或者单独调试 每个组件相当于一个lib
    • 插件化也是拆分成很多模块 包括宿主和插件 每个插件都是一个apk

    生命周期方案

    • 接口回调控制生命周期
    • 利用ActivityThread 和Instrumentation hook ProxyActivity
    • 改变AMS PMS 源码

    步骤

    ① PackageManager获取插件入口activity
    ② 构造dexclassloader更换ProxyActivity的classloader
    ③ 反射AssetManager 重新构造resources

    难点

    • 插件中 ClassLoader 的问题;
      DexClassLoader可以加载jar/apk/dex 可以加载未安装的apk; PathClassLoader只能加载已经安装过的apk
      替换宿主activity的classloader目的是 加载插件apk的class
    • 插件中的资源文件访问问题;
      AssetManager实例并且反射调用addAssetPath方法
    • 插件中 Activity 组件的生命周期问题;
      封装一个instrumentation,替换掉宿主的 (InstrumentationWrapper)
    • .so 文件加载
    • Service 插件化

    small分析

    为什么用到.so?

    • so机制让开发者最大化利用已有的C和C++代码,达到重用的效果,利用软件世界积累了几十年的优秀代码
    • so是二进制,没有解释编译的开消,用so实现的功能比纯java实现的功能要快
    • so内存分配不受Dalivik/ART的单个应用限制,减少OOM
    • 相对于java代码,二进制代码的反编译难度更大,一些核心代码可以考虑放在so中

    通过buildLib和buildBundle来把非宿主的app中的文件打包为.so文件,我们最终安装到手机上的apk其实就是只有宿主的apk和其内部的.so文件,通过加载.so文件来实现加载插件中的文件

    使用注意点

    • 模块名形如:app., lib.或者web.* ; 包名包含:.app., .lib.或者.web. Small会根据包名对插件进行归类
    • bundle.json 注册依赖模块
    • 宿主moudle不能引入依赖模块(lib) 只能是插件模块引入依赖模块
    • 列表内容更新:cleanLib->cleanBundle->buildLib(准备基础库)->buildBundle(打包所有组件)
    • 各个插件模块的fragment命名一定要是MainFragment不然会出现空指针异常
    • createObject前,需要再此页面之前已经存在activity

    核心原理

    • Android类由DexClassLoader加载
    • 安卓资源由AssetManager加载 创建AssetManager实例并且反射调用addAssetPath方法添加资源搜索路径 ;为避免id冲突宿主以及各个插件之间的资源id需要分段处理,解决方案:重新打包,重新设置id
    • 生命周期受Instrumentation监控 封装一个instrumentation,替换掉宿主的 (InstrumentationWrapper)

    关于smallLibs

    • 存放组件.so包
    • 宿主运行时自动复制其下.so到缓存区

    相关问题

    • 对Service的支持
      支持动态加载,不支持动态注册
    • 插件和宿主必须在同一个进程
    • 宿主和各个插件之间的资源可以互相访问 支持sf

    相关文章

      网友评论

          本文标题:插件化

          本文链接:https://www.haomeiwen.com/subject/pvdwmftx.html