Simple TextView.setText causa 40% de uso de la CPU

La ejecución de mi aplicación causa ~ 40% de uso de la CPU en mi teléfono:

final String position = String.format("%02d:%02d:%02d", time.getHours(), time.getMinutes(), time.getSeconds()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { c.mTxtPosition.setText(position); ... 

Al comentar el método setText , el uso de la CPU cae al nivel esperado de ~ 4%. El método se invoca cada segundo y refresca ImageViews, CustomViews … sin causar el mismo exceso de carga. Además del uso de CPU, dalvik informa constantemente la recolección de basura de alrededor de 10-1000 objetos con solo llamar a setText () .

Creando un archivo de rastreo como este:

 Debug.startMethodTracing("setText"); c.mTxtPosition.setText(position); Debug.stopMethodTracing(); 

traceview enumera los siguientes métodos como Top 5 por su CPU% correspondiente:

  • ViewParent.invalidateChildInParent (16%)
  • View.requestLayout (11%)
  • ViewGroup.invalidateChild (9%)
  • TextView.setText (7%)
  • toplevel (6%)

¿Alguien tiene una explicación para esto?

Me di cuenta de esto hace un tiempo, creo que el problema es que cada vez que llamas a setText, el tamaño del cuadro de texto puede cambiar, lo que requiere que toda la pantalla pase por relayout (costoso).

Aún no lo he probado, pero si tu cuadro de texto es simple y puede tener un tamaño relativamente fijo, tal vez trates de subclasificar TextView y crear una vista que no cambie de tamaño en setText, sino que simplemente dibuje lo que sea en el área existente? Eso ahorraría mucho tiempo.

Quizás ya hay una bandera para setText que puede hacer que lo haga, pero no estoy al tanto, aunque no he buscado de cerca.

En mi caso, actualicé un evento TextView from touch, que causa una gran cantidad de actualizaciones. La solución fue cambiar el TextView layout_width y layout_height al tamaño fijo.

algunas posibles mejoras:

  1. intente usar un controlador que actualice la vista de texto cada 0.5 segundos en lugar de un hilo que lo haga.
  2. hacer que el ejecutable sea un objeto constante final en lugar de crear uno nuevo cada segundo.
  3. considere verificar que el tiempo haya cambiado (newTimeInMs-LastPublishedTimeInMs> = 1000) antes de decirle a la vista de texto que se actualice.
  4. en lugar de String.format, intente utilizar StringBuilder. sin embargo, no disfrutará de la solución de configuración regional que ofrece String.format (por ejemplo, para los dígitos árabes).

En mi caso, fue esta propiedad de TextView:

 android:ellipsize="marquee" 

Al eliminarlo, se acelera el ajuste del texto.