En el punto de vista del código en ejecución en el hilo de la interfaz de usuario, ¿hay alguna diferencia entre:
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
o
MainActivity.this.myView.post(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
y
private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
protected void onPostExecute(Bitmap result) {
Log.d("UI thread", "I am the UI thread");
}
}
Respuestas:
Ninguno de ellos es exactamente el mismo, aunque todos tendrán el mismo efecto neto.
La diferencia entre el primero y el segundo es que si se encuentra en el hilo principal de la aplicación al ejecutar el código, el primero (
runOnUiThread()
) ejecutará elRunnable
inmediatamente. El segundo (post()
) siempre coloca elRunnable
al final de la cola de eventos, incluso si ya está en el hilo principal de la aplicación.El tercero, suponiendo que cree y ejecute una instancia de
BackgroundTask
, perderá mucho tiempo sacando un subproceso del grupo de subprocesos, para ejecutar un no operativo predeterminadodoInBackground()
, antes de hacer lo que equivale a apost()
. Este es, con mucho, el menos eficiente de los tres. ÚseloAsyncTask
si realmente tiene trabajo que hacer en un hilo de fondo, no solo para el uso deonPostExecute()
.fuente
AsyncTask.execute()
requiere que llame desde el hilo de la interfaz de usuario de todos modos, lo que hace que esta opción sea inútil para el caso de usar simplemente ejecutar código en el hilo de la interfaz de usuario desde un hilo de fondo a menos que mueva todo su trabajo de fondodoInBackground()
y lo useAsyncTask
correctamente.AsyncTask
desde el hilo de la interfaz de usuario?boolean isUiThread = (Looper.getMainLooper().getThread() == Thread.currentThread());
Looper.getMainLooper().isCurrentThread
Me gusta el comentario de HPP , se puede usar en cualquier lugar sin ningún parámetro:
fuente
Hay una cuarta forma de usar
Handler
fuente
new Handler(Looper.getMainLooper()).post(r)
, que es la forma preferida deLooper.getMainLooper()
hacer una llamada estática a main, mientras quepostOnUiThread()
debe tener una instancia deMainActivity
alcance.La respuesta de Pomber es aceptable, sin embargo, no soy un gran admirador de crear nuevos objetos repetidamente. Las mejores soluciones son siempre las que intentan mitigar el consumo de memoria. Sí, hay recolección automática de basura, pero la conservación de la memoria en un dispositivo móvil cae dentro de los límites de las mejores prácticas. El siguiente código actualiza TextView en un servicio.
Se puede usar desde cualquier lugar como este:
fuente
The best solutions are always the ones that try to mitigate memory hog
. Hay muchos otros criterios parabest
, y esto tiene un ligero olor apremature optimization
. Es decir, a menos que sepa que lo está llamando lo suficiente como para que el número de objetos creados sea un problema (en comparación con las otras diez mil formas en que su aplicación probablemente está creando basura), lo que puede serbest
es escribir el más simple (más fácil de entender ), y pasar a otra tarea.textViewUpdaterHandler
sería mejor nombrar algo comouiHandler
omainHandler
, ya que generalmente es útil para cualquier publicación en el hilo principal de la interfaz de usuario; no está en absoluto vinculado a su clase TextViewUpdater. Lo alejaría del resto de ese código y dejaría en claro que se puede usar en otro lugar ... El resto del código es dudoso, porque para evitar crear un objeto dinámicamente, divide lo que podría ser una sola llamada dos pasossetText
ypost
que dependen de un objeto de larga duración que se usa como temporal. Complejidad innecesaria y no segura para subprocesos. No es fácil de mantener.uiHandler
ytextViewUpdater
, a continuación, mejorar su clase cambiando apublic void setText(String txt, Handler uiHandler)
y añadiendo la línea métodouiHandler.post(this);
Luego la persona que llama puede hacer en un solo paso:textViewUpdater.setText("Hello", uiHandler);
. Luego, en el futuro, si necesita ser seguro para subprocesos, el método puede envolver sus declaraciones dentro de un bloqueouiHandler
y la persona que llama permanece sin cambios.A partir de Android P puedes usar
getMainExecutor()
:De los documentos para desarrolladores de Android :
Del CommonsBlog :
fuente
Si necesita usar Fragment, debe usar
en vez de
Porque habrá una excepción de puntero nulo en alguna situación como fragmento de buscapersonas
fuente
Hola chicos, esta es una pregunta básica.
utilizar Handler
fuente
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
si no se llama desde el hilo de la interfaz de usuario.