Tempi di avvio dell'app

Gli utenti si aspettano che le app si carichino rapidamente e siano reattive. Un'app con tempi di avvio lenti non soddisfa queste aspettative e può deludere gli utenti. Questo tipo di esperienza negativa può indurre un utente a valutare male la tua app sul Play Store o addirittura interrompere del tutto l'app.

Questa pagina fornisce informazioni per ottimizzare il momento del lancio dell'app, tra cui una panoramica degli elementi interni del processo di lancio, come profilare le prestazioni dell'avvio e alcuni problemi comuni relativi all'avvio con suggerimenti su come risolverli.

Comprendere i diversi stati di avvio dell'app

Il lancio dell'app può avvenire in uno dei tre seguenti stati: avvio a freddo, avvio a caldo o avvio a caldo. Ogni stato determina il tempo necessario per rendere visibile l'app all'utente. Con un avvio a freddo, la tua app si avvia da zero. Negli altri stati, il sistema deve portare l'app in esecuzione dallo sfondo in primo piano.

Ti consigliamo di eseguire sempre l'ottimizzazione in base al presupposto di un avvio a freddo. In questo modo è possibile migliorare anche le prestazioni degli avvii a caldo e a caldo.

Per ottimizzare la tua app per un avvio rapido, è utile capire cosa succede a livello di sistema e di app e come interagiscono in ciascuno di questi stati.

Due metriche importanti per determinare l'avvio dell'app sono il tempo per la visualizzazione iniziale (TTID) e il tempo di attesa completo (TTFD). Il TTID è il tempo necessario per visualizzare il primo frame, mentre il TTFD è il tempo necessario affinché l'app diventi completamente interattiva. Entrambi sono ugualmente importanti, perché il TTID fa sapere all'utente che l'app è in fase di caricamento, mentre il TTFD indica quando l'app è effettivamente utilizzabile. Se una di queste opzioni è troppo lunga, l'utente potrebbe uscire dall'app prima che venga caricata completamente.

Avvio a freddo

Un avvio a freddo fa riferimento a un'app che inizia da zero. Ciò significa che fino a questo inizio, il processo del sistema crea il processo dell'app. Gli avvii a freddo si verificano nei casi, ad esempio, che l'app viene avviata per la prima volta dall'avvio del dispositivo o da quando il sistema ha terminato l'app.

Questo tipo di avvio presenta la sfida più grande per ridurre al minimo i tempi di avvio, perché il sistema e l'app hanno più lavoro da fare rispetto agli altri stati di lancio.

All'inizio di un avvio a freddo, il sistema prevede le tre attività seguenti:

  1. Carica e avvia l'app.
  2. Mostra una finestra iniziale vuota per l'app subito dopo l'avvio.
  3. Crea la procedura dell'app.

Non appena il sistema crea il processo dell'app, quest'ultimo è responsabile delle fasi successive:

  1. Crea l'oggetto app.
  2. Avvia il thread principale.
  3. Crea l'attività principale.
  4. Aumenta le visualizzazioni.
  5. Layout dello schermo.
  6. Esegui il disegno iniziale.

Quando il processo dell'app completa la prima estrazione, il processo di sistema scambia la finestra in background visualizzata, sostituendola con l'attività principale. A questo punto, l'utente può iniziare a utilizzare l'app.

La Figura 1 mostra il modo in cui i processi del sistema e dell'app passano l'uno dall'altro.

Figura 1. Una rappresentazione visiva delle parti importanti del lancio di un'app a freddo.

Possono verificarsi problemi di prestazioni durante la creazione dell'app e dell'attività.

Creazione di app

All'avvio dell'app, la finestra iniziale vuota rimane sullo schermo finché il sistema non termina di tracciare l'app per la prima volta. A questo punto, il processo di sistema scambia la finestra iniziale per la tua app, consentendo all'utente di interagire con l'app.

Se esegui l'override di Application.onCreate() nella tua app, il sistema richiama il metodo onCreate() nell'oggetto app. In seguito, l'app genera il thread principale, noto anche come thread UI, e lo attività creando la tua attività principale.

A questo punto, i processi a livello di sistema e di app procedono secondo le fasi del ciclo di vita delle app.

Creazione di attività

Dopo che il processo dell'app ha creato l'attività, questa esegue le seguenti operazioni:

  1. Inizializza i valori.
  2. Costruttori di chiamate.
  3. Chiama il metodo di callback, come Activity.onCreate(), appropriato allo stato attuale del ciclo di vita dell'attività.

In genere, il metodo onCreate() ha l'impatto maggiore sul tempo di caricamento, perché esegue le operazioni con il sovraccarico maggiore, ovvero caricando e gonfiando le visualizzazioni e inizializzando gli oggetti necessari per l'esecuzione dell'attività.

Avvio a caldo

Un avvio tiepido comprende un sottoinsieme delle operazioni che si verificano durante un avvio a freddo. Allo stesso tempo, rappresenta un overhead maggiore rispetto a un avvio a caldo. Esistono molti stati potenziali che possono essere considerati avvii tiepidi, ad esempio:

  • L'utente torna indietro dall'app, ma poi la riavvia. Il processo potrebbe continuare a essere eseguito, ma l'app deve ricreare l'attività da zero utilizzando una chiamata a onCreate().

  • Il sistema rimuove l'app dalla memoria e l'utente la riavvia. Il processo e l'attività devono essere riavviati, ma l'attività può trarre un po' di vantaggio dal bundle di stato dell'istanza salvato passato a onCreate().

Avvio a caldo

Un avvio a caldo dell'app ha un overhead più basso rispetto a un avvio a freddo. Nell'avvio a caldo, il sistema porta la tua attività in primo piano. Se tutte le attività dell'app sono ancora presenti in memoria, l'app può evitare di ripetere l'inizializzazione degli oggetti, l'aumento artificiale del layout e il rendering.

Tuttavia, se una parte della memoria viene eliminata definitivamente in risposta a eventi di taglio della memoria, come onTrimMemory(), questi oggetti devono essere ricreati in risposta all'evento di avvio a caldo.

Un avvio a caldo mostra sullo schermo lo stesso comportamento di un avvio a freddo. Il processo di sistema mostra una schermata vuota fino a quando l'app non completa il rendering dell'attività.

Figura 2. Un diagramma con i vari stati di avvio e i relativi processi, ciascuno a partire dal primo frame disegnato.

Come identificare l'avvio dell'app in Perfetto

Per eseguire il debug dei problemi di avvio dell'app, è utile determinare cosa includere esattamente nella fase di avvio dell'app. Per identificare l'intera fase di avvio dell'app in Perfetto, segui questi passaggi:

  1. In Perfetto, trova la riga con la metrica derivata Avvio di app Android. Se non la vedi, prova ad acquisire una traccia utilizzando l'app di tracciamento del sistema sul dispositivo.

    Figura 3.La sezione della metrica Startups di Android App ha derivato in Perfetto.
  2. Fai clic sulla sezione associata e premi M per selezionarla. Le parentesi vengono visualizzate intorno alla sezione e indicano il tempo necessario. La durata viene mostrata anche nella scheda Selezione corrente.

  3. Fissa la riga Avvio di app Android facendo clic sull'icona a forma di puntina, che è visibile quando tieni il puntatore sulla riga.

  4. Scorri fino alla riga con l'app in questione e fai clic sulla prima cella per espandere la riga.

  5. Aumenta lo zoom sul thread principale, di solito in alto, premendo W (premi S, A, D per diminuire lo zoom, spostare a sinistra e spostarti a destra rispettivamente).

    Figura 4.La sezione della metrica derivata da Startup di app Android accanto al thread principale dell'app.
  6. La sezione delle metriche derivate consente di vedere più facilmente cosa è incluso esattamente nell'avvio dell'app, in modo da poter continuare a eseguire il debug in modo più dettagliato.

Utilizza le metriche per ispezionare e migliorare le startup

Per diagnosticare correttamente le prestazioni dei tempi di avvio, puoi monitorare le metriche che mostrano il tempo necessario per avviare l'app. Android offre diversi mezzi per mostrarti che la tua app ha un problema e aiutarti a diagnosticarlo. Android vitals può avvisare che si sta verificando un problema e gli strumenti di diagnostica possono aiutarti a identificarlo.

Vantaggi dell'utilizzo delle metriche per le startup

Android utilizza le metriche Tempo per la visualizzazione iniziale (TTID) e Tempo per la visualizzazione completa (TTFD) per ottimizzare gli avvii di app a freddo e a freddo. Android Runtime (ART) utilizza i dati di queste metriche per precompilare in modo efficiente il codice per l'ottimizzazione delle startup future.

L'avvio più rapido comporta un'interazione degli utenti più duratura con la tua app, il che riduce le istanze di chiusura anticipata, riavvio dell'istanza o passaggio a un'altra app.

Android vitals

Android vitals può contribuire a migliorare le prestazioni della tua app avvisandoti in Play Console quando i tempi di avvio della tua app sono eccessivi.

Android vitals considera eccessivi i seguenti tempi di avvio della tua app:

  • L'avvio a cold richiede almeno 5 secondi.
  • L'avvio a caldo richiede almeno 2 secondi.
  • L'avvio a caldo richiede 1,5 secondi o più.

Android vitals utilizza la metrica Tempo per la prima visualizzazione (TTID). Per informazioni su come Google Play raccoglie dati Android vitals, consulta la documentazione di Play Console.

Tempo di attesa per la prima schermata

Il tempo per la visualizzazione iniziale (TTID) è il tempo necessario per visualizzare il primo frame dell'interfaccia utente dell'app. Questa metrica misura il tempo necessario affinché un'app produca il primo frame, incluse l'inizializzazione del processo durante un avvio a freddo, la creazione di attività durante un avvio a freddo o a caldo e la visualizzazione del primo frame. Mantenere basso il TTID dell'app contribuisce a migliorare l'esperienza utente consentendo agli utenti di vedere rapidamente il lancio dell'app. Il TTID viene registrato automaticamente per ogni app da Android Framework. Quando ottimizzi per l'avvio dell'app, ti consigliamo di implementare reportFullyDrawn per ottenere informazioni fino a TTFD.

Il TTID viene misurato come un valore di tempo che rappresenta il tempo totale trascorso che include la seguente sequenza di eventi:

  • Avvio del processo.
  • Inizializzazione degli oggetti.
  • Creazione e inizializzazione dell'attività.
  • Ottimizzazione del layout in corso.
  • Disegna l'app per la prima volta.

Recupera TTID

Per trovare il TTID, cerca nello strumento a riga di comando di Logcat una riga di output contenente un valore denominato Displayed. Questo valore è il TTID ed è simile al seguente esempio, in cui il TTID è 3s534ms:

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms

Per trovare il TTID in Android Studio, disabilita i filtri nella visualizzazione Logcat dal menu a discesa dei filtri, quindi trova l'ora di Displayed, come mostrato nella Figura 5. La disabilitazione dei filtri è necessaria perché questo log è gestito dal server di sistema, non dall'app stessa.

Figura 5. Filtri disabilitati e valore Displayed in logcat.

La metrica Displayed nell'output di Logcat non acquisisce necessariamente la quantità di tempo necessaria prima del caricamento e della visualizzazione di tutte le risorse. Esclude le risorse a cui non si fa riferimento nel file di layout o che l'app crea nell'ambito dell'inizializzazione degli oggetti. Esclude queste risorse perché il loro caricamento è un processo in linea e non blocca la visualizzazione iniziale dell'app.

A volte la riga Displayed nell'output di Logcat contiene un campo aggiuntivo per il tempo totale. Ecco alcuni esempi:

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)

In questo caso, la prima misurazione si riferisce solo all'attività che viene tracciata per la prima volta. La misurazione del tempo di total inizia all'avvio del processo di app e può includere un'altra attività avviata per prima, ma che non mostra nulla sullo schermo. La misurazione del tempo di total viene mostrata solo quando c'è una differenza tra la singola attività e i tempi di avvio totali.

Ti consigliamo di utilizzare Logcat in Android Studio, ma se non usi Android Studio, puoi anche misurare il TTID eseguendo la tua app con il comando adb di gestione attività della shell. Ecco un esempio:

adb [-d|-e|-s <serialNumber>] shell am start -S -W
com.example.app/.MainActivity
-c android.intent.category.LAUNCHER
-a android.intent.action.MAIN

La metrica Displayed viene visualizzata nell'output di Logcat come prima. Nella finestra del terminale viene visualizzato quanto segue:

Starting: Intent
Activity: com.example.app/.MainActivity
ThisTime: 2044
TotalTime: 2044
WaitTime: 2054
Complete

Gli argomenti -c e -a sono facoltativi e ti consentono di specificare <category> e <action>.

Tempo per la visualizzazione completa

Il tempo alla visualizzazione completa (TTFD) è il tempo necessario affinché un'app diventi interattiva per l'utente. È indicato come il tempo necessario per visualizzare il primo frame dell'interfaccia utente dell'app, nonché i contenuti che vengono caricati in modo asincrono dopo la visualizzazione del frame iniziale. Generalmente, si tratta di contenuti principali caricati dalla rete o dal disco, come riportato dall'app. In altre parole, TTFD include TTID e il tempo necessario affinché l'app sia utilizzabile. Mantenere basso il valore di TTFD per l'app contribuisce a migliorare l'esperienza utente, in quanto consente agli utenti di interagire rapidamente con la tua app.

Il sistema determina il TTID quando Choreographer chiama il metodo onDraw() dell'attività e quando sa di averlo chiamato per la prima volta. Tuttavia, il sistema non sa quando determinare la TTFD perché ogni app si comporta in modo diverso. Per determinare la TTFD, l'app deve inviare un segnale al sistema quando raggiunge lo stato completamente tracciato.

Recupera TTFD

Per trovare la TTFD, segnala lo stato completamente tracciato chiamando il metodo reportFullyDrawn() di ComponentActivity. Il metodo reportFullyDrawn segnala quando l'app è completamente tracciata e in uno stato utilizzabile. Il TTFD è il tempo trascorso da quando il sistema riceve l'intent di avvio dell'app al momento in cui viene chiamato reportFullyDrawn(). Se non chiami reportFullyDrawn(), non viene segnalato alcun valore TTFD.

Per misurare la TTFD, chiama reportFullyDrawn() dopo aver disegnato completamente l'interfaccia utente e tutti i dati. Non chiamare reportFullyDrawn() prima che la finestra della prima attività venga prima tracciata e visualizzata come misurata dal sistema, in quanto poi quest'ultimo segnala il tempo misurato dal sistema. In altre parole, se chiami reportFullyDrawn() prima che il sistema rilevi il TTID, il sistema riporta sia TTID che TTFD come lo stesso valore, e questo valore è il valore TTID.

Quando utilizzi reportFullyDrawn(), Logcat visualizza un output come l'esempio seguente, in cui il TTFD è 1s54ms:

system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms

A volte l'output Logcat include un intervallo di tempo total, come discusso in Tempo per la visualizzazione iniziale.

Se i tempi di visualizzazione sono più lenti del previsto, puoi provare a identificare i colli di bottiglia nel processo di avvio.

Puoi utilizzare reportFullyDrawn() per segnalare lo stato completamente tracciato nei casi di base in cui sai che è stato raggiunto lo stato completamente tracciato. Tuttavia, nei casi in cui i thread in background devono completare le operazioni in background prima di ottenere lo stato disegnato completamente, devi ritardare reportFullyDrawn() per una misurazione più precisa del TTFD. Per scoprire come posticipare reportFullyDrawn(), consulta la sezione seguente.

Migliora la precisione dei tempi di avvio

Se per la tua app è in corso il caricamento lento e la visualizzazione iniziale non include tutte le risorse, ad esempio quando l'app recupera immagini dalla rete, ti consigliamo di ritardare la chiamata a reportFullyDrawn finché l'app non diventa utilizzabile, in modo da poter includere la compilazione dell'elenco come parte del tempo di benchmark.

Ad esempio, se l'interfaccia utente contiene un elenco dinamico, come un elenco RecyclerView o un elenco lento, questo potrebbe essere compilato da un'attività in background che viene completata dopo che l'elenco è stato disegnato per la prima volta e, di conseguenza, dopo che l'interfaccia utente è stata contrassegnata come completamente disegnata. In questi casi, la compilazione dell'elenco non è inclusa nel benchmarking.

Per includere la compilazione dell'elenco come parte delle tempistiche del benchmark, ottieni FullyDrawnReporter utilizzando getFullyDrawnReporter() e aggiungi un reporter nel codice della tua app. Rilascia il reporter al termine dell'attività in background per completare l'elenco.

FullyDrawnReporter non chiama il metodo reportFullyDrawn() finché tutti gli autori di report aggiunti non vengono rilasciati. Se aggiungi un reporter fino al completamento del processo in background, i tempi includono anche il tempo necessario per completare l'elenco nei dati relativi alle tempistiche di avvio. Questo non modifica il comportamento dell'app per l'utente, ma consente ai dati di avvio della temporizzazione di includere il tempo necessario per completare l'elenco. reportFullyDrawn() non viene chiamato finché non sono state completate tutte le attività, indipendentemente dall'ordine.

L'esempio seguente mostra come eseguire contemporaneamente più attività in background, con la possibilità di registrare il proprio reporter:

Kotlin

class MainActivity : ComponentActivity() {

    sealed interface ActivityState {
        data object LOADING : ActivityState
        data object LOADED : ActivityState
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            var activityState by remember {
                mutableStateOf(ActivityState.LOADING as ActivityState)
            }
            fullyDrawnReporter.addOnReportDrawnListener {
                activityState = ActivityState.LOADED
            }
            ReportFullyDrawnTheme {
                when(activityState) {
                    is ActivityState.LOADING -> {
                        // Display the loading UI.
                    }
                    is ActivityState.LOADED -> {
                        // Display the full UI.
                    }
                }
            }
            SideEffect {
                lifecycleScope.launch(Dispatchers.IO) {
                    fullyDrawnReporter.addReporter()

                    // Perform the background operation.

                    fullyDrawnReporter.removeReporter()
                }
                lifecycleScope.launch(Dispatchers.IO) {
                    fullyDrawnReporter.addReporter()

                    // Perform the background operation.

                    fullyDrawnReporter.removeReporter()
                }
            }
        }
    }
}

Java

public class MainActivity extends ComponentActivity {
    private FullyDrawnReporter fullyDrawnReporter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        fullyDrawnReporter = getFullyDrawnReporter();
        fullyDrawnReporter.addOnReportDrawnListener(() -> {
            // Trigger the UI update.
            return Unit.INSTANCE;
        });

        new Thread(new Runnable() {
            @Override
            public void run() {
                fullyDrawnReporter.addReporter();

                // Do the background work.

               fullyDrawnReporter.removeReporter();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                fullyDrawnReporter.addReporter();

                // Do the background work.

                fullyDrawnReporter.removeReporter();
            }
        }).start();
    }
}

Se la tua app utilizza Jetpack Compose, puoi utilizzare le API seguenti per indicare lo stato disegnato completamente:

  • ReportDrawn: indica che il componibile è immediatamente pronto per l'interazione.
  • ReportDrawnWhen: utilizza un predicato, come list.count > 0, per indicare quando il componibile è pronto per l'interazione.
  • ReportDrawnAfter: adotta un metodo di sospensione che, una volta completato, indica che il componibile è pronto per l'interazione.
Identificare i colli di bottiglia

Per cercare i colli di bottiglia, puoi utilizzare Profiler CPU di Android Studio. Per ulteriori informazioni, consulta Ispezionare l'attività della CPU con Profiler CPU.

Puoi anche ottenere informazioni sui potenziali colli di bottiglia tramite il tracciamento in linea all'interno dei metodi onCreate() delle tue app e delle tue attività. Per informazioni sul tracciamento in linea, consulta la documentazione relativa alle funzioni di Trace e la panoramica sul tracciamento del sistema.

Risolvere problemi comuni

Questa sezione illustra diversi problemi che spesso influiscono sulle prestazioni dell'avvio dell'app. Questi problemi riguardano principalmente l'inizializzazione di oggetti app e attività, nonché il caricamento delle schermate.

Inizializzazione intensiva delle app

Le prestazioni del lancio possono risentirne quando il codice esegue l'override dell'oggetto Application ed esegue logiche complesse o impegnative durante l'inizializzazione dell'oggetto. La tua app potrebbe perdere tempo durante l'avvio se le tue sottoclassi Application eseguono inizializzazioni che non devono ancora essere effettuate.

Alcune inizializzazioni potrebbero essere completamente superflue, ad esempio durante l'inizializzazione delle informazioni sullo stato dell'attività principale quando l'app viene effettivamente avviata in risposta a un intent. L'app usa solo un sottoinsieme dei dati sullo stato inizializzato in precedenza.

Altre sfide durante l'inizializzazione delle app includono gli eventi di garbage collection di grande impatto o numerosi o I/O del disco che si verificano in concomitanza con l'inizializzazione, bloccando ulteriormente il processo di inizializzazione. La garbage collection viene presa in considerazione soprattutto nel runtime Dalvik, mentre Android Runtime (ART) esegue la garbage collection contemporaneamente, riducendo al minimo l'impatto dell'operazione.

Diagnostica il problema

Puoi utilizzare il tracciamento del metodo o il tracciamento in linea per provare a diagnosticare il problema.

Tracciamento del metodo

L'esecuzione di Profiler CPU rivela che il metodo callApplicationOnCreate() alla fine chiama il tuo metodo com.example.customApplication.onCreate. Se lo strumento indica che l'esecuzione di questi metodi richiede molto tempo, approfondisci la questione per capire quali sono i passaggi in corso.

Tracciamento in linea

Utilizza il tracciamento in linea per indagare i probabili colpevoli, tra cui:

  • La funzione onCreate() iniziale dell'app.
  • Qualsiasi oggetto singleton globale inizializzato dalla tua app.
  • Eventuali I/O del disco, deserializzazione o loop stretti che potrebbero verificarsi durante il collo di bottiglia.

Soluzioni al problema

Sia che il problema sia legato a inizializzazioni non necessarie o all'I/O del disco, la soluzione è l'inizializzazione lazy. In altre parole, inizializza solo gli oggetti immediatamente necessari. Anziché creare oggetti statici globali, passa a un pattern singleton in cui l'app inizializza gli oggetti solo la prima volta che ne ha bisogno.

Inoltre, valuta la possibilità di utilizzare un framework di inserimento delle dipendenze come Hilt, che crea oggetti e dipendenze quando vengono inseriti per la prima volta.

Se la tua app utilizza fornitori di contenuti per inizializzare i componenti all'avvio, valuta l'utilizzo della libreria Avvio app.

Inizializzazione delle attività intense

La creazione di attività comporta spesso molto lavoro impegnativo. Spesso, ci sono opportunità di ottimizzare questo lavoro per ottenere miglioramenti delle prestazioni. Questi problemi comuni includono:

  • Gonfiaggio di layout grandi o complessi.
  • Blocco del disegno dello schermo su disco o I/O di rete.
  • Caricamento e decodifica di bitmap.
  • Rasterizzazione degli oggetti VectorDrawable.
  • Inizializzazione di altri sottosistemi dell'attività.

Diagnostica il problema

Anche in questo caso, il tracciamento dei metodi e il tracciamento in linea possono essere utili.

Tracciamento del metodo

Quando utilizzi il Profiler della CPU, presta attenzione ai costruttori della sottoclasse Application dell'app e ai metodi com.example.customApplication.onCreate().

Se lo strumento indica che l'esecuzione di questi metodi richiede molto tempo, valuta ulteriormente la procedura per verificare quali dati vengono eseguiti.

Tracciamento in linea

Utilizza il tracciamento in linea per indagare i probabili colpevoli, tra cui:

  • La funzione onCreate() iniziale dell'app.
  • Qualsiasi oggetto singleton globale inizializzato.
  • Eventuali I/O del disco, deserializzazione o loop stretti che potrebbero verificarsi durante il collo di bottiglia.

Soluzioni al problema

Esistono molti potenziali colli di bottiglia, ma due problemi e rimedi comuni sono i seguenti:

  • Più grande è la gerarchia delle visualizzazioni, maggiore sarà il tempo che l'app impiega per gonfiarla. Per risolvere il problema, puoi procedere in due modi:
    • Appiattisci la gerarchia delle visualizzazioni riducendo layout ridondanti o nidificati.
    • Non gonfiare le parti dell'interfaccia utente che non devono essere visibili durante il lancio. Utilizza invece un oggetto ViewStub come segnaposto per le sottogerarchie che l'app può gonfiare in un momento più opportuno.
  • Anche l'inizializzazione di tutte le risorse nel thread principale può rallentare l'avvio. Puoi risolvere il problema nel seguente modo:
    • Sposta tutte le operazioni di inizializzazione delle risorse in modo che l'app possa eseguirle in modo lento su un thread diverso.
    • Consenti all'app di caricare e visualizzare le tue viste e poi aggiorna le proprietà visive che dipendono da bitmap e altre risorse in un secondo momento.

Schermate iniziali personalizzate

Durante l'avvio potresti notare l'aggiunta di tempo aggiuntivo se in precedenza hai utilizzato uno dei seguenti metodi per implementare una schermata iniziale personalizzata in Android 11 (livello API 30) o versioni precedenti:

  • Utilizzo dell'attributo del tema windowDisablePreview per disattivare la schermata vuota iniziale disegnata dal sistema durante l'avvio.
  • È in uso un Activity dedicato.

A partire da Android 12, è necessaria la migrazione all'API SplashScreen. Questa API velocizza i tempi di avvio e ti consente di modificare la schermata iniziale nei seguenti modi:

Inoltre, la libreria di compatibilità esegue il backporting dell'API SplashScreen per garantire la compatibilità con le versioni precedenti e creare un aspetto coerente per la visualizzazione della schermata iniziale in tutte le versioni di Android.

Per maggiori dettagli, consulta la Guida alla migrazione delle schermate iniziali.