首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >闲聊MultiDex

闲聊MultiDex

作者头像
俞其荣
发布2019-07-28 14:06:00
9620
发布2019-07-28 14:06:00
举报
文章被收录于专栏:俞其荣的博客俞其荣的博客

MultiDex 是什么?

当Android系统安装一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt。DexOpt的执行过程是在第一次加载Dex文件的时候执行的。这个过程会生成一个ODEX文件,即Optimised Dex。执行ODex的效率会比直接执行Dex文件的效率要高很多。

但是在早期的Android系统中,DexOpt有一个问题,DexOpt会把每一个类的方法id检索起来,存在一个链表结构里面。但是这个链表的长度是用一个short类型来保存的,导致了方法id的数目不能够超过65536个。当一个项目足够大的时候,显然这个方法数的上限是不够的。尽管在新版本的Android系统中,DexOpt修复了这个问题,但是我们仍然需要对低版本的Android系统做兼容。

在Android 5.0之前,为了解决这个问题,Google官方推出了这个类似于补丁一样的 support-library, MultiDex。而在 Android 5.0及以后,使用了 ART 虚拟机,原生支持从 APK 文件加载多个 dex 文件。

使用方法

以下是在 minSdkVersion < 21 的使用方法。

  1. 配置build.gradle android { compileSdkVersion 21 buildToolsVersion "21.1.0" defaultConfig { ... // Enabling multidex support. multiDexEnabled true } ... } dependencies { compile 'com.android.support:multidex:1.0.3' }
  2. 继承 MultiDexApplication public class MyApplication extends MultiDexApplication { // ........... }
  3. 如果不想继承 MultiDexApplication ,可以重写 attachBaseContext 方法 @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); }

反之,如果 minSdkVersion >= 21 ,只需要以下配置即可。

    android {
        defaultConfig {
            ...
            minSdkVersion 21 
            targetSdkVersion 28
            multiDexEnabled true
        }
        ...
    }

MultiDex 原理

简单地来说,MultiDex 做的事情就是:

  1. 解压得到 dex 并进行 dexOpt ;
  2. 把主dex文件除外的 dex 文件都追加到 PathClassLoader 中 DexPathListde Element[] 数组中

熟悉组件化、热修复的同学肯定对这些已经了如指掌了吧。

MultiDex 的局限性

Dalvik 可执行文件分包支持库具有一些已知的局限性,将其纳入您的应用构建配置之中时,您应该注意这些局限性并进行针对性的测试:

• 启动期间在设备数据分区中安装 DEX 文件的过程相当复杂,如果辅助 DEX 文件较大,可能会导致应用无响应 (ANR) 错误。在此情况下,您应该通过 ProGuard 应用代码压缩以尽量减小 DEX 文件的大小,并移除未使用的那部分代码。

• 由于存在 Dalvik linearAlloc 错误(问题 22586),使用 Dalvik 可执行文件分包的应用可能无法在运行的平台版本早于 Android 4.0(API 级别 14)的设备上启动。如果您的目标 API 级别低于 14,请务必针对这些版本的平台进行测试,因为您的应用可能会在启动时或加载特定类群时出现问题。代码压缩可以减少甚至有可能消除这些潜在问题。

• 由于存在 Dalvik linearAlloc 限制(问题 78035),因此,如果使用 Dalvik 可执行文件分包配置的应用发出非常庞大的内存分配请求,则可能会在运行期间发生崩溃。尽管 Android 4.0(API 级别 14)提高了分配限制,但在 Android 5.0(API 级别 21)之前的 Android 版本上,应用仍有可能遭遇这一限制。

第一个问题的解决方法

Facebook 提出一种加载方案:将 MultiDex.install() 操作放在另外一个经常进行的。

让 Launcher Activity 在另外一个进程启动,但是 Multidex.install 还是在 Main Process 中开启,虽然逻辑上已经不承担 dexopt 的任务。 这个 Launcher Activity 就是用来异步触发 dexopt 的 ,load 完成就启动 Main Activity;如果已经loaded,则直接启动Main Process。 Multidex.install所引发的合并耗时操作,是在前台进程的异步任务中执行的,所以没有 ANR 的风险。

在 Facebook 的这个方案基础上,其实你不知道MultiDex到底有多坑 给出了一个优化后的方案。

20190709001043.png

另外,还有美团、微信的解决方案,详见 Android Dex分包最全总结:含Facebook解决方案

第二个问题的解决方法

现在开发的应用 minSdkVersion 一般都设置为 Android 4.1 。所以 API 低于 14 的不需要考虑了。

现在应该不存在哪个应用丧心病狂地向下兼容适配到 Android 2.X 了吧?

Reference

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.07.27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MultiDex 是什么?
  • 使用方法
  • MultiDex 原理
  • MultiDex 的局限性
  • Reference
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档