热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

插件化篇插件化框架对比

来看看现有插件化框架的对比。目录:MulitDex引起的问题插件化需要解决的问题与方案插件化实现方案分析对比1.MulitDex引起的问题在应用安装到手机上的时

来看看现有插件化框架的对比。

目录:


  1. MulitDex 引起的问题
  2. 插件化需要解决的问题与方案
  3. 插件化实现方案分析对比

 

 

1. MulitDex 引起的问题

在应用安装到手机上的时候 dex 文件的安装是复杂的,有可能会因为第二个 dex 文件太大导致 ANR。使用了 mulitDex 的 App 有可能在 4.0(api level 14) 以前的机器上无法启动,因为 Dalvik linearAlloc bug(Issue 22586) 。使用了 mulitDex 的 App 在 runtime期间有可能因为 Dalvik linearAlloc limit (Issue 78035) Crash。该内存分配限制在 4.0 版本被增大,但是 5.0 以下的机器上的 Apps 依然会存在这个限制。

主 dex 被 dalvik 虚拟机执行时候,哪些类必须在主 dex 文件里面这个问题比较复杂。build tools 可以搞定这个问题。但是如果你代码存在反射和 native 的调用也不保证 100% 正确。

对于 davilk 和 art 虚拟机 Mulitdex 的不同: ART 模式相比原来的 Dalvik,会在安装 APK 的时候,使用 Android 系统自带的dex2oat 工具把 APK 里面的 .dex 文件转化成 OAT 文件。

这里说一下罗迪的快速加载 Mulitdex 方案:art 虚拟机对 dex 优化需要很长时间,加载插件 dex 跳过优化实现加速,跳过会影响类加载的性能。

 

 

2. 插件化需要解决的问题与方案

 


  • 2.1 实现插件化需要解决的技术点

  • 问题 1:资源如何加载,资源冲突问题如何解决。
  • 问题 2:代码如何加载访问。
  • 问题 3:插件的管理后台包括的内容。
  • 问题 4:插件的增量更新问题。
  • 问题 5:加载插件中的 so 库。

 


  • 2.2 解决方案

针对问题 1:


原理:资源 id 是在编译时生成的,其生成的规则是 0xPPTTNNNN,PP 段是用来标记 apk 的,默认情况下系统资源 PP 是01,应用程序的 PP 是 07。TT 段,是用来标记资源类型的,比如图标、布局等,相同的类型 TT 值相同,但是同一个 TT 值不代表同一种资源,例如这次编译的时候可能使用 03 作为 layout 的 TT,那下次编译的时候可能会使用 06 作为TT的值,具体使用那个值,实际上和当前 APP 使用的资源类型的个数是相关联的。NNNN 则是某种资源类型的资源 id,默认从1 开始,依次累加。


那么我们要解决资源 id 问题,就可从 TT 的值开始入手,只要将每次编译时的 TT 值固定,即可以让资源 id 达到分组的效果,从而避免重复。例如将宿主程序的 layout 资源的 TT 固定为 33,将插件程序资源的 layout 的 TT 值固定为 03 (可不对插件程序的资源 id 做任何处理,使其使用编译出来的原生的值),即可解决资源 id 重复的问题了。

固定资源 id 的 TT 值的办法非常简单,提供一份 public.xml,在 public.xml 中指定什么资源类型以什么 TT 值开头即可。比如:

public.xml:



build.gradle:

afterEvaluate {for (variant in android.applicationVariants) {def scope = variant.getVariantData().getScope()String mergeTaskName = scope.getMergeResourcesTask().namedef mergeTask = tasks.getByName(mergeTaskName)mergeTask.doLast {copy {int i=0from(android.sourceSets.main.res.srcDirs) {include 'values/public.xml'rename 'public.xml', (i++ == 0? "public.xml": "public_${i}.xml")}into(mergeTask.outputDir)}}}
}

这样就能使用 public.xml 固定资源 id,public.xml 用来告诉 Android 资源打包工具 aapt,将类型为 drawable 的资源 ic_notice 的id 固定为 0x7f02002b。注意,在开发应用程序时,一般是不需要用到 public.xml 文件的,因为我们的资源基本上都是在内部使用的,不会导出来给第三方应用程序使用。只在内部使用的资源,不管它的 id 如何变化,我们都可以通过 R.java 文件定义的常量来正确地引用它们。只有系统定义的资源包才会使用到 public.xml 文件,因为它定义的资源是需要提供给第三方应用程序使用的。当然还有做插件化的时候,处理资源冲突问题。

还有一个方法是通过定制过的 aapt 在编译时指定插件的 PP 段的值来实现分组,重写过的 aapt 指定 PP 段来实现 id 分组。


  • 方案 1:将插件 apk 资源解压,通过操作文件的方式来使用,这个只是理论上可行,实际使用的时候还是有很多的问题。
  • 方案 2:重写 Context 的 getResource()、getAsset() 之类的方法,资源冲突需要扩展 aapt 实现。
  • 方案 3:打包后执行一个脚本修改资源 id。

 

针对问题 2:


原理说明:主要就是 classloader 加载 dex,代理模式就是本身宿主中有 Activity,通过欺骗系统来创建 Activity,欺骗系统的部分 hook 的有深有浅 (对比 DroidPlugin 和 Small),让这个 Activity 有生命周期,而动态加载模式就是运行时动态创建并编译一个 Activity 类,需要使用动态创建类的工具实现动态字节码操作。



  • 方案 1:简单加载模式。
  • 方案 2:Activity 代理模式。
  • 方案 3:动态加载模式。

 

针对问题 3:


  • 提供插件信息查询和下载,包括回滚到某一版本。
  • 管理使用插件的 apk,可以向不同版本 apk 提供不同插件。
  • MD5 校检插件的合法性。

 

 

3. 插件化实现方案分析对比

 


  • AndroidDynamicLoader

AndroidDynamicLoader 的作者是大众点评的屠毅敏,应该是最早的动态加载实现方案了。作者在介绍这个框架时形容宿主 App就好像浏览器,但它加载的并不是网页,而是运行在 Android 系统上的插件。这个方案主要是在插件中使用 Fragment,在宿主中使用 Activity 去动态加载插件中的 Fragment。
github 链接:https://github.com/mmin18/AndroidDynamicLoader


  • 23Code

23Code 并不是一个开源的项目,它是一个完整的 apk。在应用市场可以下载得到,它内部展示了一些有趣的动效,通过下载的方式,可以直接运行起来,这就是插件化的真实案例。


  • Altas

altas 是阿里的伯奎分享出来的一个插件化的方案。
分享视频链接:http://v.youku.com/v_show/id_XNTMzMjYzMzM2.html
对应的 PPT:http://club.alibabatech.org/resource_detail.htm?topicId=84

这里的分享主要是将一些思路,业务方面的场景,解决的问题。后来 github 上有了对应的开源项目叫 OpenAltas,后改名ACDD。
ACDD 的链接:https://github.com/bunnyblue/ACDD

官方对这个库的说明是非代理 Android 动态热部署框架,而且在视频介绍中,伯奎也讲到,这个方案,就是把宿主当做一个容器,动态加载对应的插件。视频中也有讲到,要做到让插件无感知地运行在这个容器中,需要 hook 很多系统层面的东西,比如:ActivityThread,LoadedApk,ContextImpl,PackageParser,ActivityManagerNative 等,即当插件需要系统的服务来提供对应功能的时候,将这个行为拦截掉,宿主就可以在插件和 Android 系统中间做些手脚了。在当时,Altas 是最为先进插件化技术了,为淘宝客户端提供了很多加载其他业务插件的能力。


  • Dynamic-load-apk

Dynamic-Load-Apk 简称 DL,这个开源框架作者是任玉刚,他的实现方式是,在宿主中埋一个代理 Activity,更改 ClassLoader后找到加载插件中的 Activity,使用宿主中的 Activity 作为代理,回调给插件中 Activity 所以对应的生命周期。这个思路与AndroidDynamicLoader 有点像,都是做一个代理,只不过 Dynamic-load-apk 加载的插件中的 Activity。
项目地址:https://github.com/singwhatiwanna/dynamic-load-apk
项目说明:http://blog.csdn.net/singwhatiwanna/article/details/40283117


  • DroidPlugin

DroidPlugin 是张勇实现的一套插件化方案,它的原理也是 Hook 客户端一侧的系统 API,可能与 Altas 所 Hook 的点不同,细想应该是基本相同的。
项目地址:https://github.com/DroidPluginTeam/DroidPlugin

项目中 DOC 文件夹有很多关于项目的讲解说明。
张勇本人对 DroidPlugin 的讲解:http://www.infoq.com/cn/presentations/the-realization-principle-and-application-of-droidplugin?utm_campaign=rightbar_v2&utm_source=infoq&utm_medium=presentations_link&utm_content=link_text
维术对这个框架的讲解:http://weishu.me/2016/01/28/understand-plugin-framework-overview/

维术的这几篇 blog 很详细滴讲解了 DroidPlugin 是如何实现四大组件的插件化的,还有几篇有规划但是没有写的方面,希望后面能补全。


  • VirtualApp

VirtualApp 作者是高中生罗迪,据说这个 Android 大牛初三的时候就开始研究双开、插件化的技术,相当了不起。项目的思路与DroidPlugin 相似,不过他没有提供 Service 的代理,而是使用 ContentProvider 来代替 Service 在宿主中作为真正的运行体。
项目地址:https://github.com/asLody/VirtualApp


  • DynamicAPK

DynamicAPK 是携程推出的动态加载方案。
项目说明:http://www.infoq.com/cn/articles/ctrip-android-dynamic-loading
项目地址:https://github.com/CtripMobile/DynamicAPK

与 ACDD 一样修改了aapt,使得插件与宿主的资源不会出现相同 id 的问题。

 

整体对比如下:

 

 

 

 


推荐阅读
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • 本文介绍了Android中的assets目录和raw目录的共同点和区别,包括获取资源的方法、目录结构的限制以及列出资源的能力。同时,还解释了raw目录中资源文件生成的ID,并说明了这些目录的使用方法。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
author-avatar
手机用户2602927443
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有