¿Cómo actualizar las vistas de texto de Android de manera eficiente?

Estoy trabajando en una aplicación de Android que encuentra problemas de rendimiento. Mi objetivo es recibir cadenas de un AsyncTask y mostrarlos en un TextView. El TextView está inicialmente vacío y cada vez que el otro proceso envía una cadena concatena el contenido actual de la vista de texto. Actualmente utilizo StringBuilder para almacenar la cadena principal y cada vez que recibo una nueva cadena, la añado al StringBuilder y llamo

myTextView.setText(myStringBuilder.toString()) 

El problema es que el proceso de fondo puede enviar hasta 100 cadenas por segundo, y mi método no es lo suficientemente eficiente.

Redibujar todo el TextView cada vez es, obviamente, una mala idea (complejidad de tiempo O (N²)), pero no estoy viendo otra solución …

¿Conoces una alternativa a TextView que podría hacer estas concatenaciones en O (N)?

Siempre y cuando haya una nueva línea entre las cadenas, podría usar un ListView para anexar las cadenas y mantener las propias cadenas en un ArrayList o LinkedList a la que se agrega como AsyncTask recibe las cadenas.

También podría considerar simplemente invalidar el TextField con menos frecuencia; Digamos 10 veces por segundo. Esto sin duda mejorará la capacidad de respuesta. Algo como lo siguiente podría funcionar:

 static long lastTimeUpdated = 0; if( receivedString.size() > 0 ) { myStringBuilder.append( receivedString ); } if( (System.currentTimeMillis() - lastTimeUpdated) > 100 ) { myTextView.setText( myStringBuilder.getChars( 0, myStringBuilder.length() ); } 

Si las cadenas vienen en ráfagas, de tal manera que tiene un retraso entre ráfagas mayor que, digamos, un segundo, restablezca un temporizador cada actualización que disparará este código para que se ejecute de nuevo para captar la parte posterior de la última ráfaga.

Finalmente encontré una respuesta con la ayuda de havexz y Greyson aquí, y algo de código aquí . Como las cadenas estaban llegando en ráfagas, he decidido actualizar la interfaz de usuario cada 100ms. Para que conste, aquí está el aspecto de mi código:

 private static boolean output_upToDate = true; /* Handles the refresh */ private Handler outputUpdater = new Handler(); /* Adjust this value for your purpose */ public static final long REFRESH_INTERVAL = 100; // in milliseconds /* This object is used as a lock to avoid data loss in the last refresh */ private static final Object lock = new Object(); private Runnable outputUpdaterTask = new Runnable() { public void run() { // takes the lock synchronized(lock){ if(!output_upToDate){ // updates the outview outView.setText(new_text); // notifies that the output is up-to-date output_upToDate = true; } } outputUpdater.postDelayed(this, REFRESH_INTERVAL); } }; 

Y lo puse en mi método onCreate() :

 outputUpdater.post(outputUpdaterTask); 

Algunas explicaciones: cuando mi aplicación llama a su método onCreate() , mi outputUpdater recibe una solicitud para actualizar. Pero esta tarea ( outputUpdaterTask ) se pone una petición de actualización 100ms más tarde. El lock se comparte con el proceso que envía las nuevas cadenas y establece output_upToDate en false.

Trate de limitar la actualización. Así que en lugar de actualizar 100 veces por segundo, ya que es la tasa de generación. Mantenga las 100 cadenas en el constructor de cadenas y luego actualice una vez por segundo.

El código debe gustar:

 StringBuilder completeStr = new StringBuilder(); StringBuilder new100Str = new StringBuilder(); int counter = 0; if(counter < 100) { new100Str.append(newString); counter++; } else { counter = 0; completeStr.append(new100Str); new100Str = new StringBuilder(); myTextView.setText(completeStr.toString()); } 

NOTA: El código de arriba es sólo para ilustración, así que puede que tenga que modificarlo según sus necesidades.

  • Acerca de la optimización de la implementación de patrones de ViewHolder en ListView
  • Webview para ampliar la presentación con el tipo de vista
  • Problema de rendimiento de PublisherAdView loadAd en Android
  • Mi aplicación se desplaza muy mal después de importar la fuente roboto en la carpeta assets / fonts
  • Boot complete broadcast procesado en serie en KITKAT 4.4.2 <ACTION_BOOT_COMPLETED> <ActivityManagerService.java>
  • ¿Existe una herramienta para eliminar las variables no deseadas, no utilizadas
  • Android - Declarativa vs interfaz de usuario programática
  • Las inserciones de SQLite se vuelven más lentas incluso con transacciones
  • Android Studio muestra que el límite de inotify de advertencia es demasiado bajo
  • ¿Por qué Android Eclipse constantemente actualiza las carpetas externas y toma forver?
  • Hacer que el emulador de Android funcione más rápido
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.