2012-06-12 10 views
11

Ho un servizio che invia un Intento alla mia attività ogni 0,1 secondi. Lo uso per aggiornare un'implementazione personalizzata di un cronometro. Qui tutto va bene. Il problema arriva quando voglio aggiornare 14 TextView che ho in un TableView all'interno di un frammento nella mia attività. Qui l'app è molto lenta.Multiple TextViews si aggiornano molto lentamente

Il metodo nella mia attività in cui riceve l'intento da parte del Servizio:

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     long milis = intent.getLongExtra("milis",0); 
     if(mFragment != null) 
     mFragment.Update(milis); 
    } 
}; 

il codice all'interno del frammento in cui posso aggiornare le TextViews:

public void actualizarTiempoJuego(long milis){ 
    // Se recuperan los tiempos acumulados y se aumenta la cantidad pasada como parámetro 
    for(int i=0;i<7;++i) { 
     long mCurrentMilis1 = mVectorMilis1.get(i); 
     long mCurrentMilis2 = mVectorMilis2.get(i); 
     TextView1 t1 = mListaTitularLayoutLocal.get(i); 
     TextView1 t2 = mListaTitularLayoutVisitante.get(i); 
     t1.setText(String.value(milis + mCurrentMilis1)); 
     t2.setText(String.value(milis + mCurrentMilis2)); 
    } 
} 

sto facendo qualcosa di sbagliato, o è solo che sto cercando di fare qualcosa di molto complesso in termini di efficienza?

+0

vorrei creare una stringa da 'Milis 'e usalo 14 volte, invece di provare a creare 14 stringhe identiche. E poi usa gli strumenti Android per verificare se uno standard per il ciclo, un ciclo per ogni ciclo o l'utilizzo di Iterator fornisce i risultati più rapidi. – Sam

+0

@ Sam. Questa è una versione leggera. Ho copiato qui così per renderlo più facile da capire. Lo modifico per renderlo più completo. – gutiory

+0

C'è più informazioni che vorresti per accettare una risposta ?? –

risposta

7

@Sherif mostra un buon punto sui valori alfa nascosti che impantanano l'applicazione molto. A seconda della piattaforma che si può anche voler controllare

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

Un'altra cosa che si può guardare in che può aiutare le prestazioni non è sparare fuori tutti quei Intenti. Una volta che inizi a sparare a intenti, stai coinvolgendo il sistema e, a seconda di come vengono risolti, potrebbe richiedere del tempo extra.

Per questo problema mi piace usare Handlers. Sono più leggeri dell'intento. Si potrebbe anche voler guardare AsyncTask. Questo è fondamentalmente come un thread, ma fornisce anche hook che vengono eseguiti sul thread dell'interfaccia utente, in modo che sia possibile eseguire entrambe le operazioni in background e aggiornare l'interfaccia utente senza dover postare i runnables.

MODIFICA: Infine, è sempre possibile eseguire i layout tramite lo strumento layoutopt. Lo stesso Romain Guy mi ha detto personalmente che se il tuo disegno è troppo lento, allora devi disegnare di meno. Basta controllare uno screenshot (da un albero di visualizzazione meno che ideale, ma entro il limite massimo) dallo strumento di creazione profili. Puoi vedere quanta parte del disegno della vista risorse occupa. È molto importante tenerlo il più snello possibile se vuoi che la tua app sia reattiva. Profiling View Drawing Resource Consumption

EDIT: E non si chiama più layoutopt, si chiama lint. Controlla ~/android-sdk/tools/

+0

HardwareAccelerated non ha aiutato a migliorare le prestazioni. Sto cercando lo strumento Link. Te lo dirò dopo. – gutiory

+0

Sì. Ho detto che l'accelerazione hardware può essere d'aiuto, a seconda della piattaforma. È inoltre necessario limitare il disegno e l'uso di intenti. Quale strumento di collegamento mi hai detto più tardi? –

+0

Scusa, volevo dire lo strumento lint. – gutiory

5

Ho affrontato una volta una situazione in cui un frammento era molto lento.

Sto solo prevedendo che il tuo frammento abbia una sorta di alfa ed è disegnato su un'attività "pesante".

La conclusione è che ogni volta che si imposta il testo di una vista testo l'intera gerarchia della vista viene invalidata.

Sembra che i frammenti abbiano questo difetto. Ad ogni modo, usa un layout al posto del frammento e controlla se rimane "lento".


inoltre: a TextView wrap_content causerà molto più ritardo dopo un setText di un TextView fill_parent.

+0

Il tuo commento sul fatto che wrap_content sia costoso ha risolto un problema che stavo facendo! Evviva! Grazie per la condivisione. – adrianmc

+0

Duuuuuude, mi hai salvato la vita, grazie !!! Cambiare la larghezza di textView in 'matchConstraint' ha funzionato. L'interfaccia utente è diventata fluida e reattiva. – Mikhail

3

Probabilmente stai andando incontro a rallentamenti dovuti alla gestione del layout con TableLayout e TextView. Ogni volta che si aggiorna il testo in uno di questi, è necessario eseguire una grande quantità di misurazioni della vista per mettere i caratteri nel posto giusto sullo schermo.Dovresti semplicemente tracciare l'app da solo usando Traceview per scoprirlo. Ulteriori informazioni: http://developer.android.com/tools/debugging/debugging-tracing.html

Ho riscontrato lo stesso identico problema con lo stesso tipo di layout (Fragment> TableLayout> Multiple TextViews). Un modo per verificare se la tua installazione TableLayout/TextView è la colpa è semplicemente sostituire tutto ciò con un singolo TextView. Probabilmente funzionerà abbastanza bene. Quindi inserisci le 14 visualizzazioni in FrameLayout o RelativeLayout. Anche se si sovrappongono tutti, dovresti comunque ottenere prestazioni decenti, perché è la complessità delle misurazioni della vista TableLayout che sta davvero causando il rallentamento.

+0

Ho fatto quello che mi hai detto. Comincio con un singolo TextView e everithing aveva ragione. Ma quando ho aggiunto 5 ulteriori TextViews, è diventato di nuovo lento. – gutiory

+0

Hai rimosso il TableLayout prima di questo test?Sono positivo al 99%: il ritardo che si sta osservando è la misurazione di View necessaria per allineare correttamente diverse righe di un layout di tabella combinate con la misurazione di TextView con testo dinamico. – Josh

+0

Sì. Ho rimosso TableLayout come suggerito. Cambio il frammento che includeva il TableLayout per le visualizzazioni di testo. – gutiory

0

Come qualcuno ha detto che è possibile utilizzare HardwareAccelerated ma questa non è una soluzione eccezionale, sprecherai RAM e CPU se non riesci a risolverlo in un modo diverso. Una soluzione probabilmente più sicurezza è ridurre il numero di TextView. Prova a ridurre 14 a 7 e andrà due volte più veloce. Di solito è difficile farlo, ma se si mettono gli oggetti in una posizione strategica, una coppia di TextView uno sopra l'altro può essere insieme se si crea un TextView con due linee. E non dimenticare che findViewById è così costoso, se usi un oggetto vista lo trovi spesso una volta e tieni il suo riferimento.

0

I benchmark sono sempre utili per determinare da dove proviene effettivamente la lentezza, ma sono abbastanza fiducioso nel suggerire che l'invio di un intent è probabilmente molto più lento dell'aggiornamento di 14 TextViews. L'invio di 10 Intenti al secondo indica che stai facendo del male (TM). Questo è semplicemente non è quello che sono per.

Sto facendo qualcosa di sbagliato, o è solo che sto cercando di fare qualcosa di molto complesso in termini di efficienza?

Aggiornamento 14 TextView al secondo non è intrinsecamente complesso; dovresti essere in grado di ottenere facilmente questo con un design dell'applicazione più appropriato. ASyncTask o Handler vengono in mente come possibili strumenti, ma è difficile sapere cosa è meglio senza sapere di più su esattamente quello che stai cercando di fare.

+0

Ho usato un Hanlder per aggiornare le TextView ma ho ancora lo stesso comportamento. – gutiory

+0

@gutiory Ti sei liberato del Servizio e degli Intenti? Aggiungere un gestore in più non renderà le cose più veloci. Sto suggerendo di utilizzare un'architettura diversa con un gestore o AsyncTask * invece * di un servizio e intenti. –

0
  • Si può provare a dichiarare Vars fuori del ciclo:

    public void actualizarTiempoJuego(long milis){ 
        // Se recuperan los tiempos acumulados y se 
        // aumenta la cantidad pasada como parámetro 
    
        long mCurrentMilis1; 
        long mCurrentMilis2; 
        TextView1 t1; 
        TextView1 t2; 
    
        for(int i=0;i<7;++i) { 
         mCurrentMilis1 = mVectorMilis1.get(i); 
         mCurrentMilis2 = mVectorMilis2.get(i); 
         t1 = mListaTitularLayoutLocal.get(i); 
         t2 = mListaTitularLayoutVisitante.get(i); 
         t1.setText(String.value(milis + mCurrentMilis1)); 
         t2.setText(String.value(milis + mCurrentMilis2)); 
        } 
    } 
    
  • E per setText() con tipo misto, si può provare setText("" + milis + mCurrentMilis2);

+0

forse blocchi "onReceive" da qualche parte, e l'utilizzo di un asynctask per l'aggiornamento dell'interfaccia utente potrebbe accelerare il processo, anche – Arcadien