Szukaj…


Wprowadzenie

DEX oznacza pliki wykonywalne kodu bajtowego aplikacji na Androida (APK) w postaci plików wykonywalnych Dalvik (DEX), które zawierają skompilowany kod użyty do uruchomienia aplikacji.

Specyfikacja pliku wykonywalnego Dalvik ogranicza całkowitą liczbę metod, do których można odwoływać się w pojedynczym pliku DEX, do 65 536 (64 KB) - w tym metod frameworku Androida, metod bibliotecznych i metod we własnym kodzie.

Aby pokonać ten limit, należy skonfigurować proces kompilacji aplikacji, aby wygenerować więcej niż jeden plik DEX, znany jako Multidex.

Uwagi

Co to jest dex?

Dex to nazwa formatu pliku i kodowania, do którego skompilowany jest kod Java systemu Android. Wczesne wersje Androida ładowały i wykonywały pliki binarne dex bezpośrednio na maszynie wirtualnej o nazwie Dalvik. Nowsze wersje Androida używają Android Runtime (ART), który traktuje pliki dex jako reprezentację pośrednią i wykonuje na nim dalsze kompilacje przed uruchomieniem aplikacji.

Dex jest bardzo starym formatem plików, jeśli chodzi o żywotność smartfonów, i został zaprojektowany dla urządzeń, których główna pamięć została zmierzona w dziesiątkach megabajtów. Ograniczenia projektowe tych dni pozostały z nami do dziś.

Problem:

Format pliku dex koduje ograniczenie liczby metod, do których można się odwoływać w pojedynczym pliku binarnym. Ponieważ część formatu pliku, w której przechowywana jest liczba odwołań, ma długość dwóch bajtów, maksymalna liczba odwołań do metod wynosi 0xFFFF lub 65535. Jeśli aplikacja zawiera więcej niż tę liczbę odwołań do metod, kompilacja się nie powiedzie.

Co z tym zrobić:

Google wyjaśnił ten problem pod nazwą Multidex. Ma składniki kompilacji i czasu wykonywania. Jak sama nazwa wskazuje, w czasie kompilacji podzieli kod między jeden lub więcej plików dex . W czasie wykonywania nauczy domyślnego ClassLoader jak wyszukiwać klasy z tych plików.

To podejście działa dobrze na nowszych urządzeniach, ale ma pewne istotne wady. Może to znacznie wydłużyć czas uruchamiania aplikacji, a na starszych urządzeniach może powodować awarie Application Not Responding .

Jeśli to możliwe, należy unikać Multidex, chociaż jest skuteczny.

Jak uniknąć limitu:

Przed skonfigurowaniem aplikacji w celu umożliwienia korzystania z 64 KB lub większej liczby referencji metod należy podjąć kroki w celu zmniejszenia całkowitej liczby referencji wywoływanych przez kod aplikacji, w tym metod zdefiniowanych przez kod aplikacji lub dołączone biblioteki. Następujące strategie mogą pomóc uniknąć przekroczenia limitu odniesienia dex:

  • Przejrzyj bezpośrednie i przechodnie zależności aplikacji - upewnij się, że wszelkie duże zależności biblioteki zawarte w aplikacji są używane w sposób, który przewyższa ilość kodu dodawanego do aplikacji. Powszechnym anty-wzorcem jest dołączanie bardzo dużej biblioteki, ponieważ użyteczne było kilka metod narzędziowych. Zmniejszenie zależności kodu aplikacji może często pomóc w uniknięciu limitu odniesienia dex.
  • Usuń nieużywany kod za pomocą ProGuard - Skonfiguruj ustawienia ProGuard dla swojej aplikacji, aby uruchomić ProGuard i upewnij się, że masz włączoną funkcję zmniejszania kompilacji wersji. Włączenie zmniejszania gwarantuje, że nie wysyłasz nieużywanego kodu z pakietami APK.

Pierwszy punkt wymaga staranności i dyscypliny ze strony dewelopera. Dołączając biblioteki innych firm, należy wziąć pod uwagę rozmiar biblioteki. Na przykład dwie popularne biblioteki JSON to Jackson i Gson. Funkcjonalnie są dość podobne, ale Gson ma większe zastosowanie w Androidzie. Jednym z powodów jest to, że Jackson waży około 9 000 metod, podczas gdy Gson wnosi 1900.

Dostępnych jest kilka narzędzi ułatwiających programistom śledzenie wielkości ich aplikacji:

  • dexcount-gradle-plugin zgłasza liczbę odwołań do metod w twoim APK lub AAR dla każdej kompilacji
  • dex-method-counts to narzędzie wiersza polecenia, które zlicza liczbę odwołań do metod w pliku APK
  • www.methodscount.com to usługa internetowa, która będzie liczyć odniesienia do metod w każdym przesłanym pliku APK.

Multidex przy użyciu MultiDexApplication bezpośrednio

Użyj tej opcji, jeśli nie potrzebujesz podklasy Application .

Jest to najprostsza opcja, ale w ten sposób nie można podać własnej podklasy Application . Jeśli potrzebna jest podklasa Application , musisz przełączyć się na jedną z innych opcji, aby to zrobić.

W przypadku tej opcji wystarczy podać w pełni kwalifikowaną nazwę klasy android.support.multidex.MultiDexApplication dla android:name właściwość tagu application w pliku AndroidManifest.xml:

<?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 poprzez rozszerzenie aplikacji

Użyj tej opcji, jeśli twój projekt wymaga podklasy Application .

Określ tę podklasę Application używając właściwości android:name w pliku manifestu wewnątrz tagu application .

W podklasie Application dodaj przesłonięcie metody attachBaseContext() , a w tej metodzie wywołaj 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);
    }
}

Upewnij się, że podklasa Application jest podana w znaczniku application w pliku AndroidManifest.xml:

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

Włączanie Multidex

Aby włączyć konfigurację multidex, potrzebujesz:

  • aby zmienić konfigurację kompilacji Gradle
  • aby użyć MultiDexApplication lub włączyć MultiDex w swojej klasie Application

Konfiguracja stopniowa

W app/build.gradle dodaj te części:

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'
}

Włącz MultiDex w swojej aplikacji

Następnie przejdź do jednej z trzech opcji:

Po dodaniu tych ustawień konfiguracji do aplikacji narzędzia do budowania systemu Android konstruują podstawowy plik dex (klasy.dex) i obsługujący go (klas2.dex, klas3.dex) w razie potrzeby.
System kompilacji następnie spakuje je do pliku APK w celu dystrybucji.

Referencje do metod liczenia na każdej kompilacji (wtyczka Dexcount Gradle)

Wtyczka dexcount zlicza metody i zasoby klasy po udanej kompilacji.

Dodaj wtyczkę do app/build.gradle :

apply plugin: 'com.android.application'

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

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

Zastosuj wtyczkę w pliku app/build.gradle :

apply plugin: 'com.getkeepsafe.dexcount'

Poszukaj danych wyjściowych wygenerowanych przez wtyczkę:

../app/build/outputs/dexcount

Szczególnie przydatny jest wykres .html w:

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

Multidex poprzez rozszerzenie MultiDexApplication

Jest to bardzo podobne do korzystania z podklasy Application i przesłaniania metody attachBaseContext() .

Jednak przy użyciu tej metody nie trzeba zastępować attachBaseContext() ponieważ jest to już zrobione w MultiDexApplication .

Rozszerz Application MultiDexApplication zamiast 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()

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

Dodaj tę klasę do pliku AndroidManifest.xml dokładnie tak, jakbyś rozszerzał aplikację:

<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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow