multidex分包续:将指定的类打包到主dex中

一、为什么有将指定的类放入主dex中的需求

我们分包的时候会遇到一个问题,因为加载和初始化的问题,如果某个类不在主dex中,那么程序就会报错,Java.lang.NoClassDefFoundError

例如:自定义主dex所包含类的过程中,有9个类必须在主dex中

<code class="hljs ruby has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">android/support/multidex/<span class="hljs-constant" style="box-sizing: border-box;">MultiDex</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>
android/support/multidex/<span class="hljs-constant" style="box-sizing: border-box;">MultiDexApplication</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>
android/support/multidex/<span class="hljs-constant" style="box-sizing: border-box;">MultiDexExtractor</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>
android/support/multidex/<span class="hljs-constant" style="box-sizing: border-box;">MultiDexExtractor</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$1</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>
android/support/multidex/<span class="hljs-constant" style="box-sizing: border-box;">MultiDex</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$4</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>
android/support/multidex/<span class="hljs-constant" style="box-sizing: border-box;">MultiDex</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$14</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>
android/support/multidex/<span class="hljs-constant" style="box-sizing: border-box;">MultiDex</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$19</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>
android/support/multidex/<span class="hljs-constant" style="box-sizing: border-box;">ZipUtil</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>
android/support/multidex/<span class="hljs-constant" style="box-sizing: border-box;">ZipUtil</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$CentralDirectory</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

这9个类必须在主dex中,否则就会出现异常,就是上面说的找不到类。在attachBaseContext方法中有个MultiDex.install(this),用来加载其他的dex文件,如果MultiDex的相关类不在主dex中,那么这些无法加载,就会报错。

注意:并不是只有这9个类是必须的,我在maindexlist.txt(这个文件做什么后面介绍)中只加入了这9个类和一个MainActivity.class,报出了找不到Android/support/multidex/MultiDex$14.class的异常,明明加入了。后来我复制了一个文件,里面有很多类,同时也有这9个类,然后就没有出异常,所以我猜测,这九个类应该还需要其他的一些类。至于复制的什么文件,下面会有介绍。

那么我们为了解决这个找不到类的问题,就必须将这样的类放入主dex中。那么如何将一个类放入主dex中呢?

二、Gradle中的配置

我们需要通过修改build.gradle文件,增加afterEvaluate区域。下面给出完整的build.gradle配置,其中1,3两项配置在dex分包方案概述与multidex包的配置使用中已经介绍过,配置如下:

<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">apply plugin: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.android.application'</span>

android {
    compileSdkVersion <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">23</span>
    buildToolsVersion <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"22.0.1"</span>

    defaultConfig {
        applicationId <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.example.gao.delete"</span>
        minSdkVersion <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">17</span>
        targetSdkVersion <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">23</span>
        versionCode <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>
        versionName <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"1.0"</span>
       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> //1</span>
        multiDexEnabled <span class="hljs-constant" style="box-sizing: border-box;">true</span>
    }
    buildTypes {
        release {
            minifyEnabled <span class="hljs-constant" style="box-sizing: border-box;">false</span>
            proguardFiles getDefaultProguardFile(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'proguard-android.txt'</span>), <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'proguard-rules.pro'</span>
        }
    }
}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">
//2</span>
afterEvaluate {
    tasks.matching {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">it</span>.name.startsWith(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'dex'</span>)
    }.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">each</span> { dx ->
       def listFile = project.rootDir.absolutePath+<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'/app/maindexlist.txt'</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (dx.additionalParameters == <span class="hljs-constant" style="box-sizing: border-box;">null</span>) {
            dx.additionalParameters = []
        }
       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> //表示当方法数越界时则生成多个dex文件(我的没有越界,貌似也生成了两个)</span>
        dx.additionalParameters += <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'--multi-dex'</span>
       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> //这个指定了listFile中的类(即maindexlist.txt中的类)会打包到主dex中,不过注意下一条。</span>
        dx.additionalParameters += <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'--main-dex-list='</span> +listFile
       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> //表明只有-main-dex-list所指定的类(在我的配置中,就是app目录下的maindexlist.txt中包含的类)才能打包到主dex中,如果没有这个选项,上个选项就会失效</span>
       dx.additionalParameters += <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'--minimal-main-dex'</span>
    }
}

dependencies {
    compile fileTree(dir: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'libs'</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">include</span>: [<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'*.jar'</span>])
    compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.android.support:appcompat-v7:24.0.0-alpha1'</span>
   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> //3</span>
    compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.android.support:multidex:1.0.0'</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li></ul>

三、创建主dex包含类的列表

为了方便,Demo下只有三个类:

这里写图片描述

根据上面builde.gradle中的配置,我们在app目录下创建一个maindexlist.txt,我们在这个txt里将我们想要放在主dex中的类写进去,自己写还是相当麻烦的,可是自己又不会脚本自动生成,没办法。不过注意一点,由于上述的配置,只有这个txt下的类才会放到主dex中,所以这个文本不能乱写,要不然各种错误,切身体会。。。

  • 我是取巧,在\app\build\intermediates\multi-dex\debug目录下找到了一个maindexlist.txt,注意,这个你改了没用,一运行又恢复了,将这个复制到app目录下,就是配置中listFile指定的路径,然后这个里面默认有很多的类,包括MainActivity,但不包括我们的Fifth.class和Sixth.class,运行,解压apk中的主dex文件,反编译,结果如下:

    这里写图片描述

  • 下面我们在app目录下的maindexlist.txt中增加一行 
    com/example/gao/delete/Sixth.class 
    ,然后重新运行,找到apk,解压,发现分了两个dex文件,我们将主dex文件反编译,主dex反编译结果如下:

    这里写图片描述

    我们可以看到,Sixth.class已经成功加入到主dex中了。

注意:

在\app\build\intermediates\multi-dex\debug目录下的maindexlist.txt复制到app目录下,不更改就只有MainActivity和一些其他类,不包括我们的Fifth.class和Sixth.class。如果我们要增加Sixth.class,如下,我们在第一行增加Sixth.class: 
这里写图片描述

如果改变并保存这个txt,这个txt就会变得很乱(不知道为什么),然后运行就失败,我是一个个回车调整成如图的格式.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值