美文网首页
插件化框架shadow的总结

插件化框架shadow的总结

作者: next_discover | 来源:发表于2019-08-06 20:40 被阅读0次
    1、插件框架有两个作用:一是“自解耦”,二是“免安装”。

    目标:“像Web一样开发App”则是一个我们后期达成的目标,这大概是“自解耦”和“免安装”的组合形式

    1.自解耦指的是:一个应用原本由一份代码编译而成,希望改成将其中的一些功能单独编译,像插件一样动态插在主应用上。这样一来可是使主应用体积变小,下载安装更方便。二来可以是比较独立的功能可以单独开发调试,甚至单独更新版本。
    2.免安装指的是:一个应用原本需要安装过程才能启动运行,希望改为无需安装即可从一个已经安装运行的App中启动起来。这一需求的主要目的是提高流量复用的能力。

    还未具备的能力:1、下载一部分启动一部分的能力。2、ContentProvider

    2、宿主和插件使用同一个包名的好处

    在执行插件代码的过程中,系统可能会调用一些(公有的或私有的)接口获取应用的applicationId,
    然而插件从真正意义上来说并没有安装到设备上,如果插件的applicationId和宿主的applicationId不相同,系统获取到插件的applicationId是一个没有安装过的包名,系统就因此crash。
    为了避免出现上述情况,有两种方法:

    1. hook系统接口,需要兼容各种OEM系统以及Android各版本
    2. 插件的applicationId和宿主的applicationId保持一致
    3、Fragment调试很麻烦:

    比如业务插件里有一个com.xx.GiftFragment类,实际运行时这个类的名字就变成了com.xx.GiftFragment_。这就导致在com.xx.GiftFragment的源码上打断点是断不下来的。必须在程序运行起来之后,用IDE的重命名功能把它改名为com.xx.GiftFragment_,使得源码和运行时类名字一致才能断点。

    4、缺点:

    Shadow开源的代码目前没有包括插件下载和版本检查实现的。
    加固
    卸载插件
    ContentProvider
    Fragment调试很麻烦
    插件A同插件B有冲突so

    插件化要解决的关键问题是:插件Activity能收到生命周期回调

    旧框架使用反射的地方:attach初始化activity,super.onCreate()获取私有变量传递给我们自己的new的activity

    shdow的关键点:使用AOP和字节码编辑将插件activity继承自activity的类替换为插件Activity继承shadowActivity

    Activity和Service最大的区别是Activity是有状态的,Service是无状态的。

    对于插件框架来说,有两点十分必要。

    一是插件一般都是热更新的,质量上要求可能会降低一些,一旦出现Crash不会影响其他进程的组件。
    二是Android的JVM虚拟机不支持Native动态库反加载,所以在同一个进程中相同so库的不同版本即不能同时加载,也不能换着加载,会造成插件和宿主存在so库冲突。

    动态化原理:

    C语言需要编译和连接两个步骤,java则编译成字节码,在运行时才会去查找用到的类,在用到的时候再去替换对应真正要启动的类

    container代理壳子:

    我们可以通过修改ClassLoader的parent,为ClassLoader新增一个parent。将原本的PathClassLoader->BootCalssLoader结构变为PathClassLoader ——> DexClassLoader ——> BootCalssLoader
    Container的动态化是使用了唯一一次反射修改私有变量。ClassLoader的parent域不属于非公开API,甚至不是Android的代码,而是JDK的代码

    view同名问题:

    插件和宿主存在同名的view会报错,因为LayoutInflater在inflated的时候做了一层缓存,以View的类名作为Key保存了Class对象。

    一个自定义的Factory,然后复制了原本内置构造逻辑的代码。在这段逻辑中,也有缓存机制。但是我们将缓存的Key添加了标记插件apk的“partKey”作为一部分,这样相同名字的View在缓存中就是不同的Key了

    webview加载插件资源的问题:

    替换ShadowWebView,拦截请求,将file:///android_asset/协议都修改成http://android.asset/协议

    so加载的问题

    插件A同插件B有冲突so,又需要在同一个进程中工作,也需要so的设计方自行解决。
    Android系统不允许在一个进程中混用64位的so和32位的so,目前的解决方案是让宿主先加载一个32位的so

    看完shadow的分析文章,对于拿来主义的人是不适合的,因为需要很多二次开发或者完善的东西,至于在这些东西中存在了多少坑需要多长时间填就不知道了,对于快速验证可行性,产品解决方案快速落地的公司或者个人也是不适合的,需要做的东西太多了。

    对于个人研究,完善shadow,让这个框架快速成熟起来是可以的。

    相关文章

      网友评论

          本文标题:插件化框架shadow的总结

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