Ricerca…


introduzione

DEX indica i file bytecode eseguibili dell'app (APK) di Android sotto forma di file Dalvik Executable (DEX), che contengono il codice compilato utilizzato per eseguire l'app.

La specifica eseguibile Dalvik limita il numero totale di metodi che possono essere referenziati all'interno di un singolo file DEX a 65.536 (64K), inclusi i metodi di framework Android, i metodi di libreria ei metodi nel proprio codice.

Per superare questo limite è necessario configurare il processo di creazione dell'app per generare più di un file DEX, noto come Multidex.

Osservazioni

Cos'è il dex?

Dex è il nome del formato file e della codifica a cui è stato compilato il codice Java di Android. Le versioni precedenti di Android caricavano ed eseguivano i binari dex direttamente in una macchina virtuale chiamata Dalvik. Le versioni più recenti di Android utilizzano Android Runtime (ART), che tratta i file dex come una rappresentazione intermedia ed esegue ulteriori compilazioni su di esso prima di eseguire l'applicazione.

Dex è un formato di file molto vecchio, in termini di durata di vita degli smartphone, ed è stato progettato per dispositivi la cui memoria principale è stata misurata in decine di megabyte. I limiti di progettazione di quei giorni sono rimasti con noi fino ad oggi.

Il problema:

Il formato del file dex codifica un limite al numero di metodi a cui è possibile fare riferimento in un singolo binario. Poiché la porzione del formato file che memorizza il numero di riferimenti è lunga due byte, il numero massimo di riferimenti al metodo è 0xFFFF o 65535. Se un'applicazione contiene più di quel numero di riferimenti al metodo, non riuscirà a compilare.

Cosa fare al riguardo:

Google ha fornito un modo per aggirare questo problema, chiamato Multidex. Ha componenti in fase di compilazione e in fase di esecuzione. Come suggerisce il nome, in fase di compilazione dividerà il codice tra uno o più file dex . Al runtime, insegnerà al ClassLoader predefinito come cercare le classi da questi file.

Questo approccio funziona bene su dispositivi più recenti, ma presenta alcuni inconvenienti sostanziali. Può aumentare drasticamente il tempo di avvio delle applicazioni e sui dispositivi più vecchi può causare errori di Application Not Responding .

Multidex, se efficace, dovrebbe essere evitato se possibile.

Come evitare il limite:

Prima di configurare la tua app per abilitare l'uso di 64K o più riferimenti al metodo, dovresti prendere provvedimenti per ridurre il numero totale di riferimenti chiamati dal tuo codice app, compresi i metodi definiti dal codice dell'app o dalle librerie incluse. Le seguenti strategie possono aiutarti a evitare di colpire il limite di riferimento di dex:

  • Verifica le dipendenze dirette e transitive della tua app : assicurati che qualsiasi dipendenza della libreria di grandi dimensioni inclusa nella tua app sia utilizzata in un modo che superi la quantità di codice che viene aggiunta all'applicazione. Un anti-pattern comune consiste nell'includere una libreria molto grande perché alcuni metodi di utilità erano utili. La riduzione delle dipendenze del codice dell'app può spesso aiutare a evitare il limite di riferimento di dex.
  • Rimuovi il codice inutilizzato con ProGuard : configura le impostazioni di ProGuard per la tua app per eseguire ProGuard e assicurati di avere il restringimento abilitato per i build di rilascio. L'attivazione del restringimento garantisce che non vengano spediti codici inutilizzati con gli APK.

Il primo punto richiede diligenza e disciplina da parte dello sviluppatore. Quando si incorporano librerie di terze parti, è necessario considerare la dimensione della libreria. Ad esempio, due famose librerie JSON sono Jackson e Gson. Funzionalmente sono abbastanza simili, ma Gson tende a vedere un maggiore uso in Android. Una delle ragioni è che Jackson pesa circa 9.000 metodi, mentre Gson contribuisce con 1.900.

Sono disponibili diversi strumenti per aiutare gli sviluppatori a tenere traccia delle dimensioni della loro applicazione:

  • dexcount-gradle-plugin riporta il numero di riferimenti al metodo nel tuo APK o AAR su ogni build
  • dex-method-counts è uno strumento della riga di comando che conta il numero di riferimenti al metodo in un APK
  • www.methodscount.com è un servizio web che conteggia i riferimenti al metodo in qualsiasi APK che carichi.

Multidex utilizzando direttamente MultiDexApplication

Usa questa opzione se non hai bisogno di una sottoclasse Application .

Questa è l'opzione più semplice, ma in questo modo non è possibile fornire la propria sottoclasse Application . Se è necessaria una sottoclasse di Application , sarà necessario passare a una delle altre opzioni per farlo.

Per questa opzione, è sufficiente specificare il nome di classe completo android.support.multidex.MultiDexApplication per android:name proprietà android:name del tag application in 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 estendendo l'applicazione

Utilizzare questa opzione se il progetto richiede una sottoclasse Application .

Specificare questa sottoclasse Application utilizzando la proprietà android:name nel file manifest all'interno del tag application .

Nella sottoclasse Application , aggiungi la sovrascrittura del metodo attachBaseContext() , e in tale metodo chiama 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);
    }
}

Assicurati che la sottoclasse Application sia specificata nel tag application di AndroidManifest.xml:

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

Abilitazione di Multidex

Per abilitare una configurazione multidex è necessario:

  • per cambiare la configurazione di build di Gradle
  • utilizzare una MultiDexApplication o abilitare il MultiDex nella classe Application

Configurazione gradle

In app/build.gradle aggiungi queste parti:

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

Abilita MultiDex nella tua applicazione

Quindi procedere con una delle tre opzioni:

Quando queste impostazioni di configurazione vengono aggiunte a un'app, gli strumenti di build di Android costruiscono un dex primario (classes.dex) e supportano (classes2.dex, classes3.dex) secondo necessità.
Il sistema di compilazione li impacchetterà quindi in un file APK per la distribuzione.

Riferimenti del metodo di conteggio su ogni build (plug-in Dexcount Gradle)

Il plugin dexcount conta i metodi e il conteggio delle risorse di classe dopo una build di successo.

Aggiungi il plugin app/build.gradle :

apply plugin: 'com.android.application'

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

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

Applicare il plug-in nel file app/build.gradle :

apply plugin: 'com.getkeepsafe.dexcount'

Cerca i dati di output generati dal plugin in:

../app/build/outputs/dexcount

Particolarmente utile è il grafico .html in:

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

Multidex estendendo MultiDexApplication

Questo è molto simile all'utilizzo di una sottoclasse Application e l'override del metodo attachBaseContext() .

Tuttavia, utilizzando questo metodo, non è necessario eseguire l'override di attachBaseContext() poiché ciò è già stato fatto nella superclasse MultiDexApplication .

Estendi MultiDexApplication anziché 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()

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

Aggiungi questa classe al tuo AndroidManifest.xml esattamente come se stessi estendendo l'applicazione:

<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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow