¿Cómo utilizamos runOnUiThread en Android?

Soy nuevo en Android y estoy tratando de usar el UI-Thread, así que escribí una actividad de prueba simple. Pero creo que he entendido mal algo, porque al hacer clic en el botón, la aplicación ya no responde

public class TestActivity extends Activity { Button btn; int i = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button)findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { runThread(); } }); } private void runThread(){ runOnUiThread (new Thread(new Runnable() { public void run() { while(i++ < 1000){ btn.setText("#"+i); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } } })); } } 

A continuación se muestra el runThread corregido de la función runThread .

 private void runThread() { new Thread() { public void run() { while (i++ < 1000) { try { runOnUiThread(new Runnable() { @Override public void run() { btn.setText("#" + i); } }); Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } 

Simplemente envuélvalo como una función, luego llame a esta función desde su hilo de fondo.

 public void debugMsg(String msg) { final String str = msg; runOnUiThread(new Runnable() { @Override public void run() { mInfo.setText(str); } }); } 

Lo tienes de frente a frente. Su clic de botón da como resultado una llamada a runOnUiThread() , pero esto no es necesario, ya que el manejador de clics ya se está ejecutando en el subproceso de la interfaz de usuario. Entonces, su código en runOnUiThread() está iniciando un nuevo hilo de fondo, donde intenta hacer operaciones de UI, que luego fallan.

En su lugar, simplemente inicie el hilo de fondo directamente desde su manejador de clics. A continuación, btn.setText() las llamadas a btn.setText() dentro de una llamada a runOnUiThread() .

 runOnUiThread(new Runnable() { public void run() { //Do something on UiThread } }); 

Hay varias técnicas que usan runOnUiThread (), permite ver todo

Este es mi hilo principal (hilo de interfaz de usuario) llamado AndroidBasicThreadActivity y voy a actualizarlo desde un hilo de trabajo de varias maneras:

 public class AndroidBasicThreadActivity extends AppCompatActivity { public static TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_android_basic_thread); textView = (TextView) findViewById(R.id.textview); MyAndroidThread myTask = new MyAndroidThread(AndroidBasicThreadActivity.this); Thread t1 = new Thread(myTask, "Bajrang"); t1.start(); } } 

1.) Pasando la instancia de Activity como argumento en el hilo de trabajo

 class MyAndroidThread implements Runnable { Activity activity; public MyAndroidThread(Activity activity) { this.activity = activity; } @Override public void run() { //perform heavy task here and finally update the UI with result this way - activity.runOnUiThread(new Runnable() { @Override public void run() { AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread."); } }); } } 

2.) Mediante el uso del método de publicación de View (Runnable Runnable) en el hilo de trabajo

 class MyAndroidThread implements Runnable { Activity activity; public MyAndroidThread(Activity activity) { this.activity = activity; } @Override public void run() { //perform heavy task here and finally update the UI with result this way - AndroidBasicThreadActivity.textView.post(new Runnable() { @Override public void run() { AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread."); } }); } } 

3.) Usando la clase Handler del paquete android.os Si no tenemos el contexto (this / getApplicationContext ()) o la instancia de Activity (AndroidBasicThreadActivity.this) entonces tenemos que usar la clase Handler como se muestra a continuación –

 class MyAndroidThread implements Runnable { Activity activity; public MyAndroidThread(Activity activity) { this.activity = activity; } @Override public void run() { //perform heavy task here and finally update the UI with result this way - new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread."); } }); } } 

Puede usar de esta muestra:

En el siguiente ejemplo, vamos a utilizar esta función para publicar el resultado de una búsqueda de sinónimos procesada por una cadena de fondo.

Para lograr el objective durante la callback de la actividad OnCreate, configuraremos onClickListener para ejecutar searchTask en un hilo creado.

Cuando el usuario hace clic en el botón Buscar, crearemos una clase anónima ejecutable que busca la palabra escrita en R.id.wordEt EditText y comienza el hilo para ejecutar Runnable.

Cuando finalice la búsqueda, crearemos una instancia de Runnable SetSynonymResult para publicar el resultado en el sinónimo TextView sobre el hilo de la interfaz de usuario.

Esta técnica a veces no es la más conveniente, especialmente cuando no tenemos acceso a una instancia de la Actividad; por lo tanto, en los siguientes capítulos, vamos a discutir técnicas más simples y más claras para actualizar la interfaz de usuario de una tarea de computación en segundo plano.

 public class MainActivity extends AppCompatActivity { class SetSynonymResult implements Runnable { String synonym; SetSynonymResult(String synonym) { this.synonym = synonym; } public void run() { Log.d("AsyncAndroid", String.format("Sending synonym result %s on %d", synonym, Thread.currentThread().getId()) + " !"); TextView tv = (TextView) findViewById(R.id.synonymTv); tv.setText(this.synonym); } } ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button search = (Button) findViewById(R.id.searchBut); final EditText word = (EditText) findViewById(R.id.wordEt); search.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Runnable searchTask = new Runnable() { @Override public void run() { String result = searchSynomim(word.getText().toString()); Log.d("AsyncAndroid", String.format("Searching for synonym for %s on %s", word.getText(), Thread.currentThread().getName())); runOnUiThread(new SetSynonymResult(result)); } }; Thread thread = new Thread(searchTask); thread.start(); } }); } static int i = 0; String searchSynomim(String word) { return ++i % 2 == 0 ? "fake" : "mock"; } } 

Fuente :

progtwigción asincrónica de Android Helder Vasconcelos

Así es como lo uso:

 runOnUiThread(new Runnable() { @Override public void run() { //Do something on UiThread } }); 

tu esto:

 @UiThread public void logMsg(final String msg) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Log.d("UI thread", "I am the UI thread"); } }); } 
  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gifImageView = (GifImageView) findViewById(R.id.GifImageView); gifImageView.setGifImageResource(R.drawable.success1); new Thread(new Runnable() { @Override public void run() { try { //dummy delay for 2 second Thread.sleep(8000); } catch (InterruptedException e) { e.printStackTrace(); } //update ui on UI thread runOnUiThread(new Runnable() { @Override public void run() { gifImageView.setGifImageResource(R.drawable.success); } }); } }).start(); }