L'applicazione potrebbe fare troppo lavoro sul suo thread principale


379

Sono nuovo nell'ambiente Android SDK / API. È il primo che sto cercando di disegnare una trama / grafico. Ho provato a eseguire diversi tipi di codici di esempio nell'emulatore usando 3 diverse librerie libere, nella schermata di layout non viene visualizzato nulla. Il logcat sta ripetendo il seguente messaggio:

 W / Trace (1378): valore imprevisto da nativeGetEnabledTags: 0
 I / Choreographer (1378): saltato 55 fotogrammi! L'applicazione potrebbe fare troppo lavoro sul suo thread principale.

Il problema non persisteva e il grafico funzionava quando eseguivo un codice di esempio relativo a una copia di valutazione di una libreria con licenza.


2
Stai disegnando i tuoi grafici su un thread separato?
Areks,

Grazie per il tuo commento, ho modificato la domanda per renderlo più chiaro. L'attività durante la corsa sta mostrando che sto eseguendo un'attività che non ha design il suo layout => mostrando uno schermo bianco.
utente2038135

1
@ Risposta No, non sto usando un thread separato.
utente2038135

1
Penso che dovresti, non è affatto consigliabile eseguire lunghe operazioni sul thread principale, perché ciò congela l'intera applicazione, puoi leggere come utilizzare i thread qui: stackoverflow.com/questions/3391272/… Ignora il "codice da fare la richiesta HTTP "ed esegui lì le tue operazioni potenzialmente lunghe.
Areks,

1
Perché non provi a cercare, troverai informazioni sul coreografo. Ti consiglio di leggere questa risposta: stackoverflow.com/questions/11266535/…
Gabriel Esteban

Risposte:


479

tratto da: UI Android: correzione dei frame saltati

Chiunque inizi a sviluppare un'applicazione Android vede questo messaggio su logcat “Choreographer (abc): frame xx saltati! L'applicazione potrebbe fare troppo lavoro sul suo thread principale. " Quindi cosa significa effettivamente, perché dovresti preoccuparti e come risolverlo.

Ciò significa che il codice sta impiegando molto tempo per l'elaborazione e che i frame vengono ignorati a causa di ciò, forse a causa di un'elaborazione pesante che stai facendo nel cuore dell'applicazione o dell'accesso al DB o di qualsiasi altra cosa che causa il thread fermati per un po '.

Ecco una spiegazione più dettagliata:

Choreographer consente alle app di connettersi al vsync e di sincronizzare correttamente le cose per migliorare le prestazioni.

Le animazioni di visualizzazione Android utilizzano internamente Choreographer per lo stesso scopo: programmare correttamente le animazioni e possibilmente migliorare le prestazioni.

Dal momento che Choreographer viene informato di tutti gli eventi vsync, posso dire se uno dei Runnable passati insieme a Choreographer.post * apis non finisce in un frame nel tempo, causando il salto dei frame.

Secondo la mia comprensione, Coreografo può rilevare solo il salto della cornice. Non ha modo di dire perché questo accada.

Il messaggio "L'applicazione potrebbe fare troppo lavoro sul suo thread principale." potrebbe essere fuorviante.

fonte: significato dei messaggi coreografi in Logcat

Perché dovresti essere preoccupato

Quando questo messaggio appare sull'emulatore Android e il numero di frame saltati è abbastanza piccolo (<100), allora puoi scommettere in sicurezza che l'emulatore è lento, cosa che accade quasi sempre. Ma se il numero di frame saltato e grande e nell'ordine di 300+, allora potrebbe esserci qualche problema serio con il tuo codice. I dispositivi Android sono disponibili in una vasta gamma di hardware a differenza dei dispositivi iOS e Windows. La RAM e la CPU variano e se desideri prestazioni e un'esperienza utente ragionevoli su tutti i dispositivi, devi risolvere questo problema. Quando i frame vengono saltati, l'interfaccia utente è lenta e ritardata, il che non è un'esperienza utente desiderabile.

Come sistemarlo

Per risolvere questo problema è necessario identificare i nodi in cui è presente o che può verificarsi una lunga durata dell'elaborazione. Il modo migliore è eseguire tutta l'elaborazione, non importa quanto piccola o grande in un thread sia separata dal thread dell'interfaccia utente principale. Che si tratti di accedere ai dati dal database SQLite o fare alcuni calcoli matematici o semplicemente ordinare un array - Fallo in un thread diverso

Ora c'è un problema qui, creerai un nuovo thread per fare queste operazioni e quando eseguirai l'applicazione, si bloccherà dicendo "Solo il thread originale che ha creato una gerarchia di viste può toccare le sue viste". Devi sapere questo fatto che l'interfaccia utente in Android può essere modificata solo dal thread principale o dal thread dell'interfaccia utente. Qualsiasi altro thread che tenta di farlo, non riesce e si arresta in modo anomalo con questo errore. Quello che devi fare è creare un nuovo Runnable all'interno di runOnUiThread e all'interno di questo runnable dovresti fare tutte le operazioni che coinvolgono l'interfaccia utente. Trova un esempio qui .

Quindi abbiamo Thread e Runnable per l'elaborazione dei dati dal thread principale, cos'altro? C'è AsyncTask in Android che consente di eseguire processi a lungo termine sul thread dell'interfaccia utente. Questo è il più utile quando le tue applicazioni sono guidate da dati o basate su API web o usi UI complesse come quelle costruite usando Canvas. Il potere di AsyncTask è che consente di fare le cose in background e una volta terminata l'elaborazione, puoi semplicemente eseguire le azioni richieste sull'interfaccia utente senza causare alcun effetto ritardato. Ciò è possibile perché AsyncTask deriva dal thread dell'interfaccia utente di Activity: tutte le operazioni che esegui sull'interfaccia utente tramite AsyncTask vengono eseguite è un thread diverso dal thread dell'interfaccia utente principale, nessun ostacolo all'interazione dell'utente.

Quindi questo è ciò che devi sapere per rendere le applicazioni Android fluide e per quanto ne so ogni principiante riceve questo messaggio sulla sua console.


41
Ho solo un'app in cui se faccio clic su un pulsante, l'immagine di sfondo del pulsante cambia e il pulsante non è selezionabile. Come sto facendo troppo lavoro :(
Remian8985

1
@ Remian8985 - La modifica dell'immagine di sfondo per il pulsante (supponendo che si stia scaricando questa immagine) dovrebbe essere eseguita in un AsyncTask, ovvero per eseguire l'operazione di download di sfondo e pubblicare il risultato sul thread dell'interfaccia utente (fornire nuovamente l'immagine). Vedi link di
BenJaminSila,

11
@BenJaminSila sta cambiando sfondo in AsyncTask? Veramente?
user25

11
@ user25 "supponendo che stai scaricando questa immagine"
forresthopkinsa il

"Quando questo messaggio appare sull'emulatore Android e il numero di frame saltati è abbastanza piccolo (<100), allora puoi fare una scommessa sicura che l'emulatore è lento" Questo si applica ancora oggi? Gli emulatori stanno diventando piuttosto veloci, giusto?
Robin Dijkhof,

243

Come altri hanno risposto sopra, "Saltato 55 frame!" significa che nella tua applicazione sono presenti elaborazioni pesanti.

Nel mio caso, non esiste un processo pesante nella mia applicazione. Ho ricontrollato e triplicato tutto e rimosso quel processo che penso fosse un po 'pesante.

Ho rimosso frammenti, attività, librerie fino a quando è rimasto solo lo scheletro. Ma il problema non è ancora scomparso. Ho deciso di controllare le risorse e ho scoperto che alcune icone e lo sfondo che uso sono piuttosto grandi poiché mi sono dimenticato di controllare le dimensioni di tali risorse.

Quindi, il mio suggerimento è che se nessuna delle risposte di cui sopra aiuta, puoi anche controllare le dimensioni dei tuoi file di risorse.


1
Ha funzionato anche per me. Avevo un'applicazione che faceva pochissimo lavoro ma era lento e lento. Continuavo a ricevere i log dei frame saltati. Una volta rimosso lo sfondo dalla mia attività, tutto andava bene. Grazie!
Akrabi,

Ottima risposta, credo che questo fosse esattamente il mio problema. Ho provato un sacco di altre soluzioni (abbastanza coinvolte) e l'app è stata altrettanto lenta. Ho eliminato tutti i servizi Web e ho cercato di ottimizzare il mio codice fino all'osso. Non ha funzionato, quindi ho visto questo. Non appena ho rimosso la mia immagine di sfondo (l'immagine più grande che ho) l'app funziona più velocemente che puoi fare clic su roba, anche con il vecchio codice "lento".
M Barbosa,

mi hai reso felice!
Nicolas Mastromarino,

:) Sei un genio assoluto.
Metin Ilhan,

@batsheva non è necessario essere 1 KB. Dipende dalle tue esigenze, diciamo che hai bisogno di un'immagine più chiara, puoi usare una risoluzione più alta, ma assicurati di dividere in diverse dimensioni nelle diverse cartelle di risorse.
Sithu,

61

Anch'io ho avuto lo stesso problema.
Il mio era un caso in cui stavo usando un'immagine di sfondo che era in drawable. Quella particolare immagine era di circa 130kB ed è stata utilizzata durante la schermata iniziale e la home page nella mia app Android.

Soluzione - Ho appena spostato quella particolare immagine nella cartella drawables-xxx dai drawable ed ero in grado di liberare molta memoria occupata in background e i frame saltanti non stavano più saltando.

Aggiornamento Utilizzare la cartella delle risorse disegnabili 'nodp' per l'archiviazione di file drawable in background.
Una cartella drawable o un drawable-nodpi qualificata per la densità avrà la precedenza?


7
Ho spostato la mia grande immagine di sfondo da drawable a mimap-xxxhdpi e ha funzionato!
bgplaya,

Hai aiutato molto. Grazie
N.Droid

2
Questa soluzione sta facendo il trucco. Sto usando drawable-xxxhdpiinvece la cartella drawableche riduce drasticamente la memoria utilizzata (~ 70 percento in meno). Inoltre, è bene sapere che schermi con le stesse dimensioni variano in dimensioni DPI. Il rapporto in pixel tra loro è ldpi = 1:0.75, mdpi = 1:1, hdpi = 1:1.5, xhdpi = 1:2, xxhdpi = 1:3, xxxhdpi = 1:4. Usando la drawable-xxxhdpicartella, permetti di ridimensionare le immagini alla dimensione del tuo dispositivo che riduce il consumo di memoria e CPU.
Timo Bähr,

2
Immagini in movimento dal drawabledi drawable-nodpiapplicazione impedisce di ottenere Out of Memory Error.
Shruti,

Oh mio Dio ... grazie! Avevo un'immagine nella cartella disegnabile e questo ha rallentato la mia app (anche se l'immagine era di soli 100kb !!!). Dopo aver generato i file drawable-xxx (ho usato Android Drawable Importer) la mia app è dannatamente veloce. Molte grazie!
errore 1337

20

Un'altra causa comune di ritardi nel thread dell'interfaccia utente è l'accesso SharedPreferences. Quando si chiama a PreferenceManager.getSharedPreferencese altri metodi simili per la prima volta, il file .xml associato viene immediatamente caricato e analizzato nello stesso thread .

Uno dei modi migliori per combattere questo problema è innescare il primo caricamento SharedPreference dal thread in background, avviato il più presto possibile (ad es. Dalla onCreatetua classe Application). In questo modo l'oggetto preferenza potrebbe essere già costruito al momento in cui si desidera utilizzarlo.

Sfortunatamente, a volte è necessario leggere un file delle preferenze durante le prime fasi di avvio (ad es. Nell'attività iniziale o persino nell'applicazione stessa). In tali casi è ancora possibile evitare di bloccare l'interfaccia utente utilizzando MessageQueue.IdleHandler. Fai tutto il necessario per eseguire il thread principale, quindi installa IdleHandler per eseguire il codice una volta che la tua attività è stata completamente disegnata. In quella Runnable dovresti essere in grado di accedere a SharedPreferences senza ritardare troppe operazioni di disegno e rendere Choreographer infelice.


1
In questo caso, dovresti preferire il metodo apply () invece di commit (). Il metodo apply () non può bloccare l'interfaccia utente. Puoi guardare da qui developer.android.com/training/data-storage/shared-preferences
Emre Gürses

16

Prova a utilizzare le seguenti strategie per migliorare le prestazioni della tua app:

  • Utilizzare la programmazione multi-thread, se possibile. I vantaggi in termini di prestazioni sono enormi, anche se il tuo smartphone ha un core (i thread possono essere eseguiti in core diversi, se il processore ne ha due o più). È utile separare la logica dell'app dall'interfaccia utente. Usa thread Java, AsyncTask o IntentService.Controllare questo .
  • Leggi e segui i suggerimenti sulle prestazioni varie del sito Web di sviluppo Android. Controllare qui .

3
il tuo primo link richiede che tu abbia "... un account validato ..." per accedervi.
Chornge

9

Ho avuto lo stesso problema. Emulatore Android ha funzionato perfettamente su Android <6.0. Quando ho usato l'emulatore Nexus 5 (Android 6.0), l'app ha funzionato molto lentamente I/Choreographer: Skipped framesnei registri.

Quindi, ho risolto questo problema modificando l' hardwareAcceleratedopzione File manifest in truequesto modo:

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

    <application android:hardwareAccelerated="true">
        ...
    </application>
</manifest>

8

Non sono un esperto, ma ho ricevuto questo messaggio di debug quando volevo inviare dati dalla mia applicazione Android a un server Web. Anche se ho usato la classe AsyncTask e ho eseguito il trasferimento dei dati in background, per recuperare i risultati dal server ho usato il metodo get () della classe AsyncTask che rende la UI sincrona, il che significa che la tua UI sarà in attesa per troppo tempo. Quindi il mio consiglio è di fare in modo che la tua app esegua tutte le attività orientate alla rete su un thread separato.


6

Ottimizza le tue immagini ... Non utilizzare immagini di dimensioni superiori a 100 KB ... Il caricamento delle immagini richiede troppa CPU e causa il blocco dell'app.


4
Diminuisci le dimensioni dell'immagine tramite il codice Java o usa Photoshop per ritagliare le immagini ..
Comprimi

5

Ho avuto lo stesso problema. Nel mio caso avevo 2 layout relativi nidificati. RelativeLayout deve sempre eseguire due passaggi di misura. Se annidate RelativeLayouts, otterrete un algoritmo di misurazione esponenziale.


4

questo di solito accade quando si eseguono enormi processi nel thread principale. va bene saltare i frame meno di 200. ma se hai più di 200 frame saltati, puoi rallentare il thread dell'interfaccia utente dell'applicazione. quello che puoi fare è fare questi processi nel nuovo thread chiamato thread di lavoro e successivamente, quando vuoi accedere e fare sth con il thread dell'interfaccia utente (es: fai qualcosa con viste, findView ecc ...) puoi usare handler o runOnUiThread (Mi piace di più) per visualizzare i risultati dell'elaborazione. questo risolve assolutamente il problema. l'utilizzo di thread di lavoro è molto utile o deve essere utilizzato anche in questi casi.


1

Ho avuto lo stesso problema. Quando ho eseguito il codice su un altro computer, ha funzionato bene. Sul mio, tuttavia, veniva visualizzato "L'applicazione potrebbe fare troppo lavoro sul suo thread principale".

Ho risolto il mio problema riavviando Android studio [File -> Cache non valide / Riavvia -> fai clic su "Invalida e riavvia"].


Non so perché la tua soluzione abbia funzionato. Comunque grazie.
Bhuvanesh BS,

1

Nel mio caso, è stato perché avevo accidentalmente impostato un punto di interruzione su un metodo. Una volta cancellato, il messaggio è andato via e le prestazioni sono migliorate molto.


0

La mia app ha avuto lo stesso problema. Ma non stava facendo altro che visualizzare l'elenco di carte e testo su di esso. Niente in esecuzione in background. Ma poi, dopo alcune indagini, è emerso che l'immagine impostata per lo sfondo delle carte lo stava causando, anche se era piccola (350kb). Quindi ho convertito l'immagine in immagini 9patch usando http://romannurik.github.io/AndroidAssetStudio/index.html .
Questo ha funzionato per me.


0

Dopo aver fatto molta ricerca e sviluppo su questo problema, ho ottenuto la soluzione,

Nel mio caso sto usando il servizio che verrà eseguito ogni 2 secondi e con runonUIThread, mi chiedevo che il problema fosse lì, ma per niente. Il prossimo problema che ho riscontrato è che sto usando una grande immagine nell'app May e questo è il problema.

Ho rimosso le immagini e impostato nuove immagini.

Conclusione: - Cerca nel tuo codice c'è qualche file raw che stai usando è di grandi dimensioni.


0

Prima leggi l'avvertimento. Dice più carico sul thread principale. Quindi quello che devi fare è semplicemente eseguire le funzioni con più lavoro in un thread.


-1

Ho avuto lo stesso problema durante lo sviluppo di un'app che utilizza molti file png disegnabili sul layout della griglia. Ho anche cercato di ottimizzare il mio codice per quanto possibile .. ma non ha funzionato per me .. Poi ho provato a ridurre le dimensioni di quei png .. e indovino che funzioni assolutamente bene .. Quindi il mio suggerimento è di ridurre dimensione delle risorse estraibili se presenti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.