关于Android MultiDex的问题

这段时间研究了一下Android MultiDex,这个东西乍看起来很简单,其实涉及到很多东西,本文就来讲讲这个,想到哪就说到哪。

分包主要是因为包太大了,低端手机安装可能会失败,或者Dex加载的时候会崩溃,所以分成多个包,跟启动相关的放在主Dex,其余的不那么紧急的放在副Dex,然后启动的时候去动态加载。

首先来看看主Dex,所谓跟启动相关的主要就是四大组件,所以四大组件直接引用到的类都要放在主Dex中,否则启动时找不到类就悲剧了,毕竟动态加载副Dex可能会挺耗时的。Android Studio的build tool会自动帮你完成分包,将Android Manifest中定义的四大组件直接引用到的类都放在主Dex中,其余的丢到副Dex。不过也不保证百分百没问题,比如你用反射或者So引用副Dex中的类也许这个脚本就会瞎掉了。当然我们也可以自己写个脚本去分析APP启动需要引用到的类,方法是在APP启动完毕时打出ClassLoader中所有已加载过的类就行了。

接下来再来说说这个副Dex加载的问题,如果这个副Dex比较大,加载起来可能挺耗时,为什么呢?耗时主要在于Dexopt优化。Dexopt优化时机通常有两个,一个是APP安装的时候,这时候只会优化主Dex。第二个是ClassLoader加载Dex时,不过如果已经优化过了就不会再优化了。所以在APP启动时动态加载副Dex仅在第一次才会挺耗时,之后就非常快了。现在关键就在于怎么处理第一次加载Dex耗时的问题,因为是在Application里加载的,容易ANR。我们可以另开一个线程来加载,不过可能还没等到加载完,主Dex中就要引用到副Dex里的类了,当然这个概率不会太大,因为我们前面提到过主Dex里已经给所有要直接引用的类都包含进去了,所以短时间内不会出岔子。但是事情就怕万一,如果真出现这种情况,我们不能眼睁睁看着程序崩溃。

接下来就讨论几种解决方案:

第一种,美团的方案,拦截Activity的启动过程,当发现要启动的Activity还没加载好的时候,直接改成跳到另一个LoadingActivity,等加载完毕后再跳到真正的目标。至于怎么拦截Activity的启动,可以参考我之前的文章如何Hook Activity的启动。不过对于其余的组件比如Service、广播这种后台型的就有点奇怪了,冷不丁会冒出一个LoadingActivity显得不那么自然。相比之下,下面的解决方案会好一些。

第二种,微信的解决方案,由于Dex只有没有优化过的时候才会调用Dexopt,所以也就是说第一次才会耗时,之后都很快,那我们重点解决第一次就好了,只是第一次慢点用户基本还可以接受。在Application启动时如果发现Dex未优化,我们就启动LoadingActivity,同时Application中继续加载Dex,即便耗时也不会ANR。因为LoadingActivity跑在新的进程,并且是当前的前台进程,而Application成了后台进程,不会导致ANR。当Dex加载完毕后就跳转到真正的Launcher Activity,并杀掉LoadingActivity。这种解决方案总体来说还是不错的,唯一的问题可能是LoadingActivity要启动在一个新进程,也许会比较耗时,我们可以优化一下,判断Dex加载会不会耗时,如果会耗时就放在一个子线程中加载,然后在当前进程中跳转到LoadingActivity,等到Dex加载完了再跳到Launcher Activity。如果Dex加载不会耗时,就直接在主线程中加载了,然后也没必要跳到Loading Activity了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值