working thread runonuithread run not activity android multithreading user-interface arguments

not - Android: ¿cómo pasar datos a Runnable en runOnUiThread?



runonuithread(() (6)

El problema que encontraste es que

Las clases internas en Java capturan ("de cerca") el ámbito léxico en el que están definidas. Pero solo capturan variables que son declaradas "finales".

Si esto está claro como barro, hay una buena discusión de los detalles aquí: No se puede referir a una variable no final dentro de una clase interna definida en un método diferente

Pero tu solución se ve bien. Además, siempre que los data sean definitivos, podría simplificar el código a esto:

public void OnNewSensorData(final Data data) { runOnUiThread(new Runnable() { public void run() { // use data here data.doSomething(); } }); }

Necesito actualizar alguna interfaz de usuario y hacerlo dentro del hilo de la interfaz de usuario mediante el uso de runOnUiThread
Ahora los datos para la interfaz de usuario provienen del otro subproceso, representado por los data aquí.

¿Cómo puedo pasar los datos a Runnable, para que puedan usarse para actualizar la interfaz de usuario? Android no parece permitir el uso de datos directamente. ¿Hay una manera elegante de hacer esto?

public void OnNewSensorData(Data data) { runOnUiThread(new Runnable() { public void run() { //use data } }); }

Mi solución consistía en crear una información private Data sensordata dentro del ejecutable y asignarle datos. Esto funciona solo si los Data data originales son definitivos.

public void OnNewSensorData(final Data data) { runOnUiThread(new Runnable() { private Data sensordata = data; public void run() { //use sensordata which is equal to data } }); }


Este es un caso típico en el que se llama al servicio de devolución de llamada para actualizar una cadena de estado de IU (TextView textStatus). El servicio puede ser roscado.

La muestra combina la verificación de si es necesaria la redirección de hilos y la redirección real:

// service callbacks public void service_StatusTextChanged(final String s) { if( isOnUiThread() ) { textStatus.setText(s); } else { runOnUiThread(new Runnable() { @Override public void run() { textStatus.setText(s); } }); } } static public boolean isOnUiThread() { return Thread.currentThread() == Looper.getMainLooper().getThread(); }

Consulte también ¿Cómo comprobar si se está ejecutando en el hilo de la interfaz de usuario en Android?


Si desea evitar el uso de una variable final intermedia (como lo describe Dan S), puede implementar Runnable con un método adicional para establecer Datos:

public class MyRunnable implements Runnable { private Data data; public void setData(Data _data) { this.data = _data; } public void run() { // do whatever you want with data } }

A continuación, puede llamar al método de esta manera:

public void OnNewSensorData(Data data) { MyRunnable runnable = new MyRunnable(); runnable.setData(data); runOnUiThread(runnable); }

también podría hacer que el constructor de MyRunnable tome la instancia de Data como un argumento:

public class MyRunnable implements Runnable { private Data data; public MyRunnable(Data _data) { this.data = _data; } public void run() { ... } }

y luego diga runOnUiThread (nuevo MyRunnable (data));


Tendrá que actualizar cada vez que su programa tenga nuevos Data que quiera mostrar. Su segundo código de lista aquí es la forma estándar de lograr esto. Puede haber algunos errores si continúa actualizando los Data en el hilo. Si este es el caso, considere bloquear el hilo hasta que la interfaz de usuario termine de actualizar o copiar los datos en otro objeto de Data .

Lo que está sucediendo internamente es que la JVM está copiando la referencia al objeto de Data para cuando se ejecutará la clase anónima. Data almacenados en el interior todavía se pueden cambiar. Si su método requiere cambios adicionales a los Data use otra variable (referencia de objeto) como: final Data finalData = data; . También puede eliminar la línea private Data sensordata = data; y usa los datos directamente en tu método de ejecución.

Puede que no parezca elegante, pero esta es la forma en que Java pasa las variables de objeto a clases anónimas. Hay una sintaxis más nueva en Java Language versión 7, pero Android es compatible con Java Language versión 5 y 6.


Tuve un problema similar en el que quería pasar información al hilo. Para resolverlo con el sistema Android, modifico la respuesta de corsiKa en: ¿Se puede ejecutar con un parámetro?

Puede declarar un derecho de clase en el método y pasar el parámetro como se muestra a continuación:

void Foo(String str) { class OneShotTask implements Runnable { String str; OneShotTask(String s) { str = s; } public void run() { someFunc(str); } } runOnUiThread(new OneShotTask(str)); }


public static Activity globalContext = null; CommonSetting.globalContext = this;// put this in MainACtivity.onCreate() public void createToastShort(final String message) { runOnUiThread(new Runnable() { public void run() { Toast.makeText(CommonSetting.globalContext, message, Toast.LENGTH_SHORT).show(); } }); }