zoukankan      html  css  js  c++  java
  • 【Android

    一、什么是MultiDex

            随着时代的进步,人们对手机 APP 的需求越来越大,越来越苛刻,很多APP都变得很大,再加上APP都不可避免的需要导入一些框架、第三方类库等等,就更加大了项目的整体文件体系。如果文件太多,系统可能会报如下错误:

    UNEXPECTED TOP-LEVEL EXCEPTION:  
    java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536  
    at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:501)  
    at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:282)  
    at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:490)  
    at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:167)  
    at com.android.dx.merge.DexMerger.merge(DexMerger.java:188)  
    at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:439)  
    at com.android.dx.command.dexer.Main.runMonoDex(Main.java:287)  
    at com.android.dx.command.dexer.Main.run(Main.java:230)  
    at com.android.dx.command.dexer.Main.main(Main.java:199)  
    at com.android.dx.command.Main.main(Main.java:103)

            Android基于JAVA语言,JAVA语言在编译之后都会生成字节码文件.class,在Android中,这些文件都被存储在一个.dex文件中。由于DEX文件的格式限制,其中的Method、Field、Class的个数都不能超过short类型的最大值65535,如果超过了这个值,就会报上面的错误。

            为了解决这个问题,Google - Android在API 21的时候为广大程序员提供了一个通用的解决方案,就是今天要说的MultiDex方案。这个方案让Android系统可以在原始的DEX文件存满之后自动生成一个新的DEX文件,从而解决这个DEX溢满的问题。

    二、MultiDex的配置

            MultiDex的配置主要是在Gradle文件中进行的,但是不仅需要配置Module中的Gradle文件,还需要配置项目根目录下的Gradle文件。

            首先,我们先来配置Module中的Gradle文件,文件中的代码如下:

    apply plugin: 'com.android.application'
    
    android {
        // productFlavors是为了避免每次运行都把DEX重新加载一遍而设置的两套运行配置
        productFlavors {
            dev {
                minSdkVersion 21
            }
            prod {
                minSdkVersion 14
            }
        }
        compileSdkVersion 24
        buildToolsVersion "24.0.2"
        defaultConfig {
            applicationId "com.example.itgungnir.testmultidex"
            minSdkVersion 11
            targetSdkVersion 24
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
            // 设置MultiDex可用
            multiDexEnabled true
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
        // 保证其他的lib没有被preDex
        dexOptions {
            preDexLibraries = false
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
            exclude group: 'com.android.support', module: 'support-annotations'
        })
        compile 'com.android.support:appcompat-v7:24.2.1'
        testCompile 'junit:junit:4.12'
        // MultiDex的依赖
        compile 'com.android.support:multidex:1.0.0'
    }

            从代码中可以看到,这里主要做了以下更改:

    •         在android代码块中加入了productFlavors和dexOptions两个子代码块;
    •         添加了MultiDex的依赖包;
    •         在defaultConfig代码块中设置开启了MultiDex。

            配置完Module下的Gradle文件,接下来配置Project下的Gradle文件。文件中的代码如下:

    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.2.0'
        }
    }
    
    allprojects {
        repositories {
            jcenter()
        }
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }
    
    // 保证dex_files文件中指定的文件都加载到Main Dex中
    afterEvaluate {
        tasks.matching {
            it.name.startsWith('dex')
        }.each { dx ->
            if (dx.additionalParameters == null) {
                dx.additionalParameters = []
            }
            dx.additionalParameters += '--multi-dex'
            dx.additionalParameters += "--main-dex-list=$projectDir/dex_files".toString()
        }
    }

            可以看到,这里主要添加了afterEvaluate代码块,最后一行中的dex_files是一个.txt文件,其中存放着想要默认加载到MainDex中的所有文件。这个dex_files文件是和这个Gradle文件在同一级目录下,以下是dex_files.txt文件中的代码(大家可以根据需要添加):

    android/support/multidex/BuildConfig/class
    android/support/multidex/MultiDex$V14/class
    android/support/multidex/MultiDex$V19/class
    android/support/multidex/MultiDex$V4/class
    android/support/multidex/MultiDex/class
    android/support/multidex/MultiDexApplication/class
    android/support/multidex/MultiDexExtractor$1/class
    android/support/multidex/MultiDexExtractor/class
    android/support/multidex/ZipUtil$CentralDirectory/class
    android/support/multidex/ZipUtil/class

            最后,需要在项目的Application文件中注入MultiDex,代码如下:

    public class MyApplication extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
        }
    
        @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
            // 将MultiDex注入到项目中
            MultiDex.install(this);
        }
    }

            别忘了在Manifest文件中注册Application:

    android:name=".MyApplication"

            到此为止,MultiDex就已经配置好了,妈妈再也不用担心我的项目dex溢出啦~~

  • 相关阅读:
    netty源码深度分析
    《深入探索Netty原理及源码分析》文集小结
    Netty 那些事儿 ——— 心跳机制
    CSS实现单行、多行文本溢出显示省略号(…)
    测试
    PHP 二维数组根据某个字段排序
    PHP生成图片验证码、点击切换实例
    正确设置网站title、keywords、description(转载)
    nginx上支持.htaccess伪静态的配置实例
    百度编辑器Ueditor增加字体的修改方法
  • 原文地址:https://www.cnblogs.com/itgungnir/p/6210902.html
Copyright © 2011-2022 走看看