サーチ…


前書き

DEXは、アプリを実行するために使用されるコンパイルされたコードを含むDalvik Executable(DEX)ファイルの形式でAndroidアプリの(APK)実行可能なバイトコードファイルを意味します。

Dalvik実行ファイル仕様では、DEXファイル内で参照できるメソッドの総数が、独自のコードでAndroidフレームワークメソッド、ライブラリメソッド、およびメソッドを含む65,536(64K)に制限されています。

この制限を克服するには、複数のDEXファイル(Multidex)を生成するようにアプリケーションビルドプロセスを設定する必要があります。

備考

dexとは何ですか?

Dexは、Android Javaコードがコンパイルされるファイル形式とエンコーディングの名前です。 Androidの初期のバージョンでは、Dalvikという仮想マシンにdexバイナリを直接ロードして実行します。 Androidの最近のバージョンでは、Androidランタイム(ART)が使用されています。これは、 dexファイルを中間表現として扱い、アプリケーションを実行する前にそれをさらにコンパイルします。

Dexはスマートフォンの寿命の点で非常に古いファイル形式であり、主メモリが数十メガバイトで測定されたデバイス用に設計されています。当時のデザインの限界が今も残っています。

問題:

dexファイル形式は、1つのバイナリで参照できるメソッドの数の制限をエンコードします。参照の数を格納するファイル形式の部分は2バイト長であるため、メソッド参照の最大数は0xFFFF 、つまり65535です。アプリケーションにその数よりも多くのメソッド参照が含まれていると、コンパイルが失敗します。

それについて何をすべきか:

GoogleはMultidexと呼ばれるこの問題を回避する手段を提供しています。コンパイル時および実行時のコンポーネントがあります。その名前が示すように、コンパイル時には、1つ以上のdexファイル間でコードを分割します。実行時に、デフォルトのClassLoaderこれらのファイルからクラスをルックアップする方法を教えます。

このアプローチは、より新しいデバイスではうまくいくが、いくつかの大きな欠点がある。これにより、アプリケーションの起動時間が大幅に短縮され、古いデバイスではApplication Not Responding障害が発生する可能性がありApplication Not Responding

可能であれば、Multidexは効果的ですが避けてください。

限界を避ける方法:

64K以上のメソッド参照を使用できるようにアプリを設定する前に、アプリコードで呼び出された参照の総数を減らすための手順を実行する必要があります。以下の戦略は、dex参照制限を回避するのに役立ちます。

  • アプリの直接的および推移的な依存関係を確認する - アプリケーションに追加する大きなライブラリ依存関係を、アプリケーションに追加するコードの量よりも多く使用するようにします。一般的な反パターンは、いくつかのユーティリティメソッドが有用であったため、非常に大きなライブラリを含めることです。アプリケーションコードの依存関係を減らすと、dex参照の制限を避けることができます。
  • ProGuardを使用して未使用のコードを削除する - ProGuardを実行するようにアプリケーションのProGuard設定を構成し、リリースビルドで縮小が有効になっていることを確認します。縮小を有効にすると、未使用のコードをAPKで配送しないようにすることができます。

最初の点は、開発者の側で勤勉と規律を必要とします。サードパーティライブラリを組み込む場合は、ライブラリのサイズを考慮する必要があります。たとえば、人気のあるJSONライブラリの2つは、JacksonとGsonです。機能的にはまったく似ていますが、GsonはAndroidでの使用が増えています。 1つの理由は、ジャクソンが約9,000の方法で体重を測定するのに対し、Gsonは1,900に寄与しているということです。

開発者がアプリケーションのサイズを把握するのに役立つツールがいくつかあります。

  • dexcount-gradle-pluginは、各ビルドのAPKまたはAARのメソッド参照の数をレポートします
  • dex-method-countsは、APK内のメソッド参照の数を数えるコマンドラインツールです
  • www.methodscount.comはアップロードするAPKのメソッド参照を数えるWebサービスです。

MultiDexApplicationを直接使用したMultidex

Applicationサブクラスを必要としない場合は、このオプションを使用します。

これは最も簡単なオプションですが、独自のApplicationサブクラスを提供することはできません。 Applicationサブクラスが必要な場合は、他のオプションの1つに切り替える必要があります。

このオプションの場合、AndroidManifest.xmlのapplicationタグのandroid:nameプロパティに完全修飾クラス名android.support.multidex.MultiDexApplicationを指定するだけapplication

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

アプリケーションを拡張することによるMultidex

プロジェクトにApplicationサブクラスが必要な場合は、このオプションを使用します。

applicationタグ内のマニフェストファイルのandroid:nameプロパティを使用して、このApplicationサブクラスを指定しApplication

Applicationサブクラスで、 attachBaseContext()メソッドのオーバーライドを追加し、そのメソッドでMultiDex.install()呼び出します。

package com.example;

import android.app.Application;
import android.content.Context;

/**
 * Extended application that support multidex 
 */
public class MyApplication extends Application {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
}

ApplicationサブクラスがAndroidManifest.xmlのapplicationタグで指定されていることを確認します。

<application
    android:name="com.example.MyApplication"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name">
</application>

マルチディックスの有効化

multidex構成を有効にするには、次のものが必要です。

  • あなたのGradleビルド設定を変更する
  • MultiDexApplicationを使用するか、 ApplicationクラスでMultiDexを有効にする

グラデル構成

app/build.gradleに次の部分を追加します:

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.1"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 24
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}

アプリケーションでMultiDexを有効にする

次に、3つのオプションのいずれかを実行します。

これらの設定がアプリに追加されると、Androidビルドツールは必要に応じて主要dex(classes.dex)とサポート(classes2.dex、classes3.dex)を構築します。
ビルドシステムは、それらをAPKファイルにパッケージ化して配布します。

すべてのビルドでメソッド参照の数をカウントする(Dexcount Gradle Plugin)

dexcountプラグインは、ビルドが成功した後のメソッドとクラスリソースの数をカウントします。

プラグインをapp/build.gradle追加します:

apply plugin: 'com.android.application'

buildscript {
    repositories {
        mavenCentral() // or jcenter()
    }

    dependencies {
        classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.5.5'
    }
}

プラグインをapp/build.gradleファイルに適用します。

apply plugin: 'com.getkeepsafe.dexcount'

プラグインによって生成された出力データを探します:

../app/build/outputs/dexcount

特に便利なのは、.htmlチャートです。

../app/build/outputs/dexcount/debugChart/index.html

MultiDexApplicationを拡張したMultidex

これは、 Applicationサブクラスを使用してattachBaseContext()メソッドをオーバーライドするattachBaseContext()と非常によく似ています。

ただし、このメソッドを使用すると、 attachBaseContext()はすでにMultiDexApplicationスーパークラスでオーバーライドされているため、オーバーライドする必要はありません。

Application代わりにMultiDexApplicationを拡張する:

package com.example;

import android.support.multidex.MultiDexApplication;
import android.content.Context;

/**
 * Extended MultiDexApplication 
 */
public class MyApplication extends MultiDexApplication {

     // No need to override attachBaseContext()

     //..........
}

アプリケーションを拡張している場合とまったく同じように、このクラスをAndroidManifest.xmlに追加してください:

<application
    android:name="com.example.MyApplication"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name">
</application>


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow