Android
Multidex- und Dex-Methodenlimit
Suche…
Einführung
DEX bedeutet ausführbare Bytecode-Dateien von Android-Apps (APK) in Form von Dalvik Executable-Dateien (DEX-Dateien), die den kompilierten Code enthalten, der zum Ausführen Ihrer App verwendet wird.
Die Dalvik Executable-Spezifikation begrenzt die Gesamtzahl der Methoden, die in einer einzelnen DEX-Datei referenziert werden können, auf 65.536 (64 KB). Dies schließt Android-Framework-Methoden, Bibliotheksmethoden und Methoden in Ihrem eigenen Code ein.
Um dieses Limit zu überwinden, müssen Sie den App-Erstellungsprozess so konfigurieren, dass er mehr als eine DEX-Datei generiert, die als Multidex bezeichnet wird.
Bemerkungen
Was ist dex
Dex ist der Name des Dateiformats und der Kodierung, für die Android Java-Code kompiliert wird. In früheren Android-Versionen wurden dex
Binärdateien direkt in einer virtuellen Maschine namens Dalvik geladen und ausgeführt. Neuere Versionen von Android verwenden die Android Runtime (ART), die dex
Dateien als Zwischendarstellung behandelt und vor dem Ausführen der Anwendung weitere Kompilierungen dex
.
Dex ist ein sehr altes Dateiformat in Bezug auf die Lebensdauer von Smartphones und wurde für Geräte entwickelt, deren Hauptspeicher in Dutzenden Megabytes gemessen wurde. Die gestalterischen Einschränkungen dieser Tage sind bis heute geblieben.
Das Problem:
Das dex
Dateiformat kodiert eine Begrenzung für die Anzahl der Methoden, die in einer einzelnen Binärdatei referenziert werden können. Da der Teil des Dateiformats, in dem die Anzahl der Verweise gespeichert ist, zwei Byte lang ist, beträgt die maximale Anzahl der Methodenverweise 0xFFFF
oder 65535. Wenn eine Anwendung mehr als diese Anzahl von Methodenverweisen enthält, wird die Kompilierung fehlschlagen.
Was Sie dagegen tun können:
Google hat dieses Problem umgangen, genannt Multidex. Es enthält Kompilierungszeit- und Laufzeitkomponenten. Wie der Name schon sagt, wird der Code bei der Kompilierung in eine oder mehrere dex
Dateien aufgeteilt. Zur Laufzeit wird dem Standard- ClassLoader
wie Klassen aus diesen Dateien ClassLoader
werden.
Dieser Ansatz funktioniert gut mit neueren Geräten, weist jedoch einige erhebliche Nachteile auf. Dies kann die Startzeit für Anwendungen erheblich verlängern und auf älteren Geräten kann es zu Fehlern bei der Application Not Responding
führen.
Multidex sollte zwar wirksam sein, jedoch möglichst vermieden werden.
Wie man das Limit vermeidet:
Bevor Sie Ihre App für die Verwendung von Methodenreferenzen mit 64 KB oder mehr konfigurieren, sollten Sie die Gesamtzahl der durch Ihren App-Code aufgerufenen Referenzen reduzieren, einschließlich der durch Ihren App-Code oder die enthaltenen Bibliotheken definierten Methoden. Mit den folgenden Strategien können Sie vermeiden, die Dex-Referenzgrenze zu erreichen:
- Überprüfen Sie die direkten und transitiven Abhängigkeiten Ihrer App - Stellen Sie sicher, dass die Abhängigkeit einer großen Bibliothek, die Sie in Ihre App aufnehmen, auf eine Weise verwendet wird, die die Menge des der Anwendung hinzugefügten Codes überwiegt. Ein häufiges Anti-Pattern ist das Einschließen einer sehr großen Bibliothek, da einige Hilfsmethoden nützlich waren. Durch das Reduzieren der Abhängigkeiten Ihres App-Codes können Sie häufig die Dex-Referenzgrenze vermeiden.
- Ungenutzten Code mit ProGuard entfernen - Konfigurieren Sie die ProGuard-Einstellungen für Ihre App, um ProGuard auszuführen, und stellen Sie sicher, dass die Verkleinerung für Release-Builds aktiviert ist. Durch das Aktivieren der Verkleinerung wird sichergestellt, dass Sie nicht verwendeten Code mit Ihren APKs versenden.
Der erste Punkt erfordert Sorgfalt und Disziplin des Entwicklers. Bei der Einbindung von Bibliotheken von Drittanbietern muss die Größe der Bibliothek berücksichtigt werden. Zum Beispiel sind zwei beliebte JSON-Bibliotheken Jackson und Gson. Funktionell sind sie sich ziemlich ähnlich, aber Gson sieht in Android einen stärkeren Einsatz. Ein Grund ist, dass Jackson rund 9.000 Methoden wiegt, während Gson 1.900 beiträgt.
Es gibt verschiedene Tools, mit denen Entwickler die Größe ihrer Anwendung nachverfolgen können:
- dexcount-gradle-plugin meldet die Anzahl der Methodenverweise in Ihrem APK oder AAR in jedem Build
- dex-method-count ist ein Befehlszeilentool, das die Anzahl der Methodenverweise in einer APK zählt
- www.methodscount.com ist ein Webservice, der die Methodenreferenzen in jeder APK zählt, die Sie hochladen.
Multidex durch direkte Verwendung von MultiDexApplication
Verwenden Sie diese Option, wenn Sie keine Application
benötigen.
Dies ist die einfachste Option, aber auf diese Weise können Sie keine eigene Application
bereitstellen. Wenn eine Application
benötigt wird, müssen Sie zu einer der anderen Optionen wechseln.
android.support.multidex.MultiDexApplication
für diese Option einfach den vollqualifizierten Klassennamen android.support.multidex.MultiDexApplication
für die Eigenschaft android:name
des application
in AndroidManifest.xml an:
<?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 durch Erweiterung der Anwendung
Verwenden Sie diese Option, wenn für Ihr Projekt eine Application
erforderlich ist.
Geben Sie diese Application
mithilfe der android:name
-Eigenschaft in der Manifestdatei innerhalb des application
.
attachBaseContext()
in der Application
die attachBaseContext()
Methode außer Kraft, und rufen MultiDex.install()
in dieser Methode 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);
}
}
Stellen Sie sicher, dass die Application
im application
Ihrer AndroidManifest.xml angegeben ist:
<application
android:name="com.example.MyApplication"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
</application>
Aktivieren von Multidex
Um eine Multidex-Konfiguration zu ermöglichen, benötigen Sie:
- um die Gradle Build-Konfiguration zu ändern
- Verwenden Sie eine
MultiDexApplication
oder aktivieren Sie die MultiDex in IhrerApplication
Klasse
Gradle Konfiguration
In app/build.gradle
fügen Sie diese Teile hinzu:
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'
}
Aktivieren Sie MultiDex in Ihrer Anwendung
Fahren Sie dann mit einer von drei Optionen fort:
Wenn diese Konfigurationseinstellungen einer App hinzugefügt werden, erstellen die Android-Build-Tools nach Bedarf einen primären Dex (classes.dex) und Unterstützung (classes2.dex, classes3.dex).
Das Build-System packt sie dann zur Verteilung in eine APK-Datei.
Zählmethodenreferenzen für jedes Build (Dexcount Gradle Plugin)
Das dexcount-Plugin zählt Methoden und Klassenressourcen nach einem erfolgreichen Build.
Fügen Sie das Plugin im app/build.gradle
:
apply plugin: 'com.android.application'
buildscript {
repositories {
mavenCentral() // or jcenter()
}
dependencies {
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.5.5'
}
}
Wenden Sie das Plugin in der Datei app/build.gradle
:
apply plugin: 'com.getkeepsafe.dexcount'
Suchen Sie nach den vom Plugin generierten Ausgabedaten:
../app/build/outputs/dexcount
Besonders nützlich ist das .html-Diagramm in:
../app/build/outputs/dexcount/debugChart/index.html
Multidex durch Erweiterung von MultiDexApplication
Dies ist sehr ähnlich der Verwendung einer Application
und dem Überschreiben der attachBaseContext()
Methode.
Bei Verwendung dieser Methode müssen Sie attachBaseContext()
jedoch nicht überschreiben, da dies bereits in der MultiDexApplication
Superklasse geschieht.
Erweitern Sie MultiDexApplication
anstelle von Application
:
package com.example;
import android.support.multidex.MultiDexApplication;
import android.content.Context;
/**
* Extended MultiDexApplication
*/
public class MyApplication extends MultiDexApplication {
// No need to override attachBaseContext()
//..........
}
Fügen Sie diese Klasse genau zu Ihrer AndroidManifest.xml hinzu, als ob Sie Application erweitern würden:
<application
android:name="com.example.MyApplication"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
</application>