En un servicio de Android, he creado hilos para realizar alguna tarea en segundo plano.
Tengo una situación en la que un hilo necesita publicar cierta tarea en la cola de mensajes del hilo principal, por ejemplo a Runnable
.
¿Hay una manera de conseguir Handler
del hilo principal y post Message
/ Runnable
a de mi otro hilo?
Gracias,
Respuestas:
NOTA: Esta respuesta ha recibido tanta atención que necesito actualizarla. Desde que se publicó la respuesta original, el comentario de @dzeikei ha recibido casi tanta atención como la respuesta original. Así que aquí hay 2 posibles soluciones:
1. Si su hilo de fondo tiene una referencia a un
Context
objeto:Asegúrese de que sus subprocesos de trabajo en segundo plano tengan acceso a un objeto de contexto (puede ser el contexto de la aplicación o el contexto del servicio). Luego solo haz esto en el hilo de fondo del trabajador:
2. Si su hilo de fondo no tiene (o necesita) un
Context
objeto(sugerido por @dzeikei):
fuente
Handler
(o usa laHandler.Callback
interfaz), suhandleMessage()
método SOLO será llamado para los mensajes que se hayan publicado usando su controlador. El hilo principal está usando un controlador diferente para publicar / procesar mensajes para que no haya conflicto.Handler mainHandler = new Handler(Looper.getMainLooper());
new Runnable(){@Override public void run() {....}};
Como un comentador a continuación señaló correctamente, esta no es una solución general para los servicios, solo para los hilos lanzados desde su actividad (un servicio puede ser un hilo, pero no todos lo son). Sobre el complicado tema de la comunicación de actividad de servicio, lea toda la sección de Servicios del documento oficial: es complejo, por lo que sería útil comprender los conceptos básicos: http://developer.android.com/guide/components/services.html # Notificaciones
El siguiente método puede funcionar en los casos más simples.
Si te entiendo correctamente, necesitas ejecutar algún código en el hilo GUI de la aplicación (no puedo pensar en nada más llamado hilo "principal"). Para esto hay un método sobre
Activity
:Doc: http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29
Espero que esto sea lo que estás buscando.
fuente
Service
. No se puede usarrunOnUiThread()
en aService
. Esta respuesta es engañosa y no aborda la pregunta formulada.Hay otra forma simple, si no tiene acceso al contexto.
1) Cree un controlador desde el looper principal:
2) Implemente una interfaz Runnable:
3) Publique su Runnable en el uiHandler:
Eso es todo ;-) Diviértete con los hilos, pero no olvides sincronizarlos.
fuente
Si ejecuta código en un hilo, por ejemplo, retrasando alguna acción, entonces necesita invocar
runOnUiThread
desde el contexto. Por ejemplo, si su código está dentro de laMainActivity
clase, use esto:Si su método se puede invocar desde main (UI thread) o desde otros hilos, necesita una verificación como:
fuente
Service
. No se puede usarrunOnUiThread()
en aService
.Activity
documentación,runOnUiThread()
es un método deActivity
. No es un métodoService
, por lo tanto, no puede usarlo. ¿Qué podría ser más claro que eso?Un bloque de código condensado es el siguiente:
Esto no implica pasar la referencia de Actividad o la referencia de Aplicación.
Equivalente de Kotlin:
fuente
Versiones Kotlin
Cuando estés en una actividad , usa
Cuando tenga contexto de actividad , mContext luego use
Cuando se encuentre en un lugar donde no haya contexto disponible , use
fuente
runOnUiThread(){...}
La forma más sencilla, especialmente si no tiene un contexto, si está utilizando RxAndroid, puede hacer:
fuente
Código de Kotlin más preciso utilizando el controlador:
fuente
Un método que se me ocurre es este:
1) Deje que la interfaz de usuario se una al servicio.
2) Exponga un método como el siguiente
Binder
que registra suHandler
:3) En el subproceso de la interfaz de usuario, llame al método anterior después de vincularse al servicio:
4) Use el controlador en el hilo del Servicio para publicar su tarea:
fuente
HandlerThread
Es una mejor opción para los hilos normales de Java en Android.requestHandler
post
unaRunnable
tarea enrequestHandler
Comunicación con UI Thread de
HandlerThread
Handler
conLooper
para hilo principal:responseHandler
yhandleMessage
método de anulaciónRunnable
Tarea interna de otro hilo (HandlerThread
en este caso), llamesendMessage
alresponseHandler
sendMessage
invocación de este resultadohandleMessage
enresponseHandler
.Message
proceso y actualícelo, actualice la interfaz de usuarioEjemplo : actualización
TextView
con datos recibidos de un servicio web. Dado que el servicio web debe invocarse en un subproceso que no sea UI, creadoHandlerThread
para la Operación de red. Una vez que obtenga el contenido del servicio web, envíe un mensaje a su manejador de subprocesos principales (UI Thread) y queHandler
manejará el mensaje y actualizará la IU.Código de muestra:
Artículos utiles:
handlerthreads-and-why-you-should-should-uses-them-in-your-android-apps
android-looper-handler-handlerthread-i
fuente
Sé que esta es una vieja pregunta, pero me encontré con un hilo principal que utilizo tanto en Kotlin como en Java. Puede que esta no sea la mejor solución para un servicio, pero para llamar a algo que cambiará la interfaz de usuario dentro de un fragmento, esto es extremadamente simple y obvio.
Java (8):
Kotlin:
fuente
Sigue este método. De esta manera, simplemente puede actualizar la interfaz de usuario desde un hilo de fondo. runOnUiThread funciona en el hilo principal (UI). Creo que este fragmento de código es menos complejo y fácil, especialmente para principiantes.
en el caso de un servicio
crear un controlador en el oncreate
entonces úsalo así
fuente
para Kotlin, puede usar las corountinas de Anko :
actualizar
obsoleto
fuente
Así que lo más útil es hacer algo así:
Y después:
fuente
Esto también puede funcionar en una clase de servicio sin problemas.
fuente
Con Kotlin, es así dentro de cualquier función:
fuente
Activity
.