插件化开发时,想要使app启动很快,需要将主dex中只是包含首页以及基础模块的功能,其他的功能放到从dex文件中,这样就可以加快app的启动速度。那如何将核心首页以及基础模块的class文件打包到主dex文件中呢?下面来实现这个过程。
1.首先要是项目支持multidex,要是项目支持multidex,需要完成下面两个步骤
a.需要在module级别的build.gradle文件中配置
android {
defaultConfig {
// 设置支持multidex
multiDexEnabled true
}
}
dependencies {
//引入对multidex支持的库
compile 'com.android.support:multidex:1.0.1'
}
b.完成这些配置后,需要在自定义的application中的attachBaseContext方法中添加如下代码:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
完成了这两个步骤后,项目才支持多dex。
2,要明确主dex文件中要包含哪些class文件,明确后,在module的build.gradle所在的目录下,新建一个maindexlist.txt文件,并将这些class文件所在的路径都写入到这个文件中。
3.在build.gradle文件中,在加入如下配置信息
android {
defaultConfig {
// 设置支持multidex
multiDexEnabled true
}
//新增的配置信息
dexOptions{
preDexLibraries = false
additionalParameters = [ //配置multidex参数
'--multi-dex',//多dex分包
'--set-max-idx-number=30000',//每个包内方法数上限
'--main-dex-list='+projectDir+'/maindexlist.txt', //打包到主classes.dex的文件列表
'--minimal-main-dex'
]
}
}
dependencies {
//引入对multidex支持的库
compile 'com.android.support:multidex:1.0.1'
}
处理完后,打包apk,这样就会将maindexlist文件中指定的class文件打包到主dex文件中。这个就是将指定的class文件打包到主dex中的操作步骤,下面结合一个实际案例,来演示。
新建一个项目,在项目中新建一个名为plugin1的module,plugin1的结构如下图:
上图中build.gradle的配置信息如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "com.android.skill"
minSdkVersion 14
targetSdkVersion 28
versionCode 1
versionName "1.0"
// 设置支持multidex
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
dexOptions{
preDexLibraries = false
additionalParameters = [ //配置multidex参数
'--multi-dex',//多dex分包
'--set-max-idx-number=30000',//每个包内方法数上限
'--main-dex-list='+projectDir+'/maindexlist.txt', //打包到主classes.dex的文件列表
'--minimal-main-dex'
]
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:28.0.0'
compile 'com.android.support.constraint:constraint-layout:1.1.3'
testCompile 'junit:junit:4.12'
androidTestCompile('com.android.support.test.espresso:espresso-core:+', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:multidex:1.0.1'
//依赖mypluglibrary库
compile project(path:':mypluglibrary')
}
自定义的application中的代码如下:
import android.app.Application;
import android.content.Context;
import android.support.multidex.MultiDex;
import android.util.Log;
public class PluginOneApplication extends Application {
private static final String TAG = "MY_LOG";
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
@Override
public void onCreate() {
super.onCreate();
}
}
maindexlist.txt文件中的信息如下(com/android/skill,这个是项目的包名):
com/android/skill/bean/Person.class
com/android/skill/MainActivity.class
com/android/skill/PluginOneApplication.class
com/android/skill/PluginReceiverOne.class
com/android/skill/PluginReceiverTwo.class
这些文件,可以在项目的文件夹目录下去查看(注意,不要通过AS的目录结构查看,因为通过AS的目录结构查看,会漏掉XXX$1.class这样的class文件),下面是本案例的这些class文件的位置
将上图红框中这些class文件写入到maindexlist.txt文件中。
通过上面的步骤,就完成了将指定的class文件打包的主dex的功能。为了方便演示,指定和未定class到主dex的区别,新添加一个mypluglibrary库,将这个库的引入到plugin1这个module中,如果指定了只是将plugin1中的class文件打包到主dex中,则在生成的apk文件中,解压后是不会再主dex文件中看到mypluglibrary库的文件的。如果未指定将plugin1中的文件打包到主dex,则会在主dex中是可以看到mypluglibrary库中的 文件的。下面看看mypluglibrary库的结构图
在plugin1这个module中依赖mypluglibrary这个库
dependencies {
...
//依赖mypluglibrary库
compile project(path:':mypluglibrary')
}
完成上述步骤后,执行plugin1这个module,找到生成的apk文件,将apk文件,拖动到AS中,可以看到如下
从上图中,可以发现,确实使用多dex,图中有classes.dex和classes2.dex,其中,下面的大的红框中的就是在maindexlist.txt文件中指定的要将将这些文件打包打主dex的文件。
如果在plugin1的build.gradle文件中,去掉
additionalParameters = [ //配置multidex参数
'--multi-dex',//多dex分包
'--set-max-idx-number=30000',//每个包内方法数上限
'--main-dex-list='+projectDir+'/maindexlist.txt', //打包到主classes.dex的文件列表
'--minimal-main-dex'
]
这个配置,在执行plugin1这个module,在将重新生成的apk包拖到AS中,可以看到:
上图中,只有一个classes.dex,没有classes2.dex,并且,这个主classes.dex文件中是包含了依赖的库mypluglibrary的文件的,下面红框中的就是主dex文件包含的依赖库的文件。可以看出,未指定将哪些class文件放入到主dex,则在打包时,会根据单个dex的方法数是否会超过65535个方法来将主项目的类先添加后,如果方法数还未超过65535,则继续将依赖的库中的文件打包到主dex中。
如果在进行分包时报
java.io.FileNotFoundException: xxx\xxx\build\intermediates\transforms\dex\debug\folders\1000\1f\main\classes.dex\classes.dex (系统找不到指定的路径。)
则表示,项目还未支持multidex,需要进行multidex相关的配置,并在自定义的application中,调用MultiDex.install(this);方法。