¿Por qué mi aplicación Android salta los marcos cuando se llama a Thread.sleep?

Estoy escribiendo una aplicación de Android que necesita mostrar algún texto para unos pocos milésimas de segundo, luego en blanco de nuevo. Lo que tengo ahora es que muestra el texto, a continuación, utilizando Thread.sleep, a continuación, establecer el texto de nuevo a null. En cambio, lo que sucede es que al presionar el botón, la aplicación se bloquea por el tiempo establecido, el texto nunca aparece, y el logcat dice: "Saltará xxx marcos! La aplicación puede estar haciendo demasiado trabajo en su hilo principal". ¿Qué está pasando, y hay una mejor manera de hacer las cosas?

Trate de usar un runnable.

 private Handler mHandler = new Handler(); //code to make text appear... mHandler.postDelayed(makeTextDisapear , 3000); // Replace 3000 with the number of milliseconds you want the text to display. private Runnable makeTextDisapear = new Runnable() { public void run() { // code to make text dissapear } }; 

Mientras que otras respuestas ayudan a resolver su problema, su pregunta fue también por qué sucede esto:

Llamar cualquiera de los métodos estáticos Thread.sleep() coloca el Thread del cual se invocó el método en un estado de pausa para (aproximadamente) la cantidad de tiempo que especifica (no se garantiza que coincida exactamente con el tiempo especificado).

En Android, las operaciones de Ui tienen que realizarse en el hilo "ui" principal, ya que el framework Ui no está diseñado para ser seguro de subprocesos. Es decir, cuando se establece el texto de un TextView , tiene que invocar textView.setText(...) en el subproceso principal. setText enviará un mensaje al Looper principal para volver a diseñar e invalidar el TextView (y los padres). En algún momento en el futuro cercano, esos mensajes serán procesados ​​y la jerarquía de la vista será actualizada.

setText no hace este trabajo directamente porque esta carga de trabajo es pesada, y hacerlo directamente no permitiría que el marco para agrupar dichas solicitudes.

Si invoca Thread.sleep(...) , está poniendo el hilo ui principal en un estado de pausa, sin embargo, es este hilo el que normalmente realizará el re-diseño y la invalidación de TextView y los padres.

Android quiere ser capaz de hacer un nuevo marco (si algo ha cambiado) en menos de 16ms para mantener un mayor de 60fps. Si su hilo principal está haciendo algo intensivo, o se detiene (por dormir) durante un tiempo significativo que podría amenazar a los 16 ms, el mensaje de error que está viendo se publica en logcat.

Mientras que en Lollipop la representación real se realiza en su propio hilo de render, todavía necesita actualizaciones oportunas del hilo principal.

En cuanto a cómo solucionar esto, vea la respuesta de Jason, o, alternativamente, publicar un retrasado ejecutables a la vista en sí (en lugar de una instancia de manejador directamente) mediante

 textView.setText("show me!"); textView.postDelayed(new Runnable() { public void run() { textView.setText(""); } }, 30); 

Si esto ocurre regularmente, evite la asignación del Runnable cada vez manteniéndolo como un campo.

Tenga en cuenta que en cualquier caso, la creación de una clase interna anónima (el Runnable ) tiene el potencial de pérdida de memoria de la actividad, pero eso es una historia diferente.

  • Android: ¿Estancias / niveles de sueño en un dispositivo Android?
  • Retardo de tiempo en Android
  • Cómo evitar dormir en Android
  • ¿Por qué mi app de Android llama a Create () cuando el sueño inicia en mi vista pero no desde la pantalla de inicio?
  • ¿Puedo impedir que el teléfono se quede dormido en una página web?
  • Desactivar el reposo en determinadas actividades
  • Cómo identificar el móvil está inactivo?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.