Как использовать runOnUiThread

Я научился что-то делать в UI-Thread, поэтому я написал простую тестовую активность. Но я думаю, что я что-то не понял, потому что, когда я нажимаю кнопку, приложение больше не переписывается

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(); } } } })); } } 

Ниже исправлен фрагмент функции 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(); } 

Просто оберните его как функцию, затем вызовите эту функцию из фонового потока.

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

У вас есть это в обратном порядке. runOnUiThread() кнопки приводит к вызову runOnUiThread() , но это не требуется, поскольку обработчик кликов уже запущен в потоке пользовательского интерфейса. Затем ваш код в runOnUiThread() запускает новый фоновый поток, где вы пытаетесь выполнять операции пользовательского интерфейса, которые затем терпят неудачу.

Вместо этого просто запустите фоновый поток непосредственно из обработчика кликов. Затем завершите вызовы btn.setText() внутри вызова runOnUiThread() .

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

Существует несколько методов использования runOnUiThread (), позволяет видеть все

Это мой основной поток (поток пользовательского интерфейса), называемый AndroidBasicThreadActivity, и я собираюсь обновить его из рабочего потока различными способами –

 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.) Передав экземпляр Activity как аргумент в рабочий поток

 class MyAndroidThread implements Runnable { Activity activity; public MyAndroidThread(Activity activity) { this.activity = activity; } @Override public void run() { activity.runOnUiThread(new Runnable() { @Override public void run() { AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread."); } }); } } 

2.) Используя метод View's post (Runnable runnable) в рабочем потоке

 class MyAndroidThread implements Runnable { Activity activity; public MyAndroidThread(Activity activity) { this.activity = activity; } @Override public void run() { AndroidBasicThreadActivity.textView.post(new Runnable() { @Override public void run() { AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread."); } }); } } 

3.) Используя класс Handler из пакета android.os Если у нас нет контекста (this / getApplicationContext ()) или экземпляра Activity (AndroidBasicThreadActivity.this), тогда мы должны использовать класс Handler, как показано ниже:

 class MyAndroidThread implements Runnable { Activity activity; public MyAndroidThread(Activity activity) { this.activity = activity; } @Override public void run() { new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread."); } }); } } 

Вы можете использовать этот образец:

В следующем примере мы собираемся использовать этот объект для публикации результата поиска синонимов, который был обработан фоновым потоком.

Чтобы достичь цели во время обратного вызова активности OnCreate, мы настроим onClickListener для запуска searchTask в созданном потоке.

Когда пользователь нажимает кнопку «Поиск», мы создаем анонимный класс Runnable, который ищет слово, введенное в Rid.wordEt EditText, и запускает поток для выполнения Runnable.

Когда поиск будет завершен, мы создадим экземпляр Runnable SetSynonymResult, чтобы опубликовать результат в синониме TextView по потоку пользовательского интерфейса.

Этот метод когда-то не самый удобный, особенно когда у нас нет доступа к экземпляру Activity; Поэтому в следующих главах мы обсудим более простые и более чистые методы обновления пользовательского интерфейса из задачи фоновых вычислений.

 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"; } } 

Источник :

Асинхронное программирование на Android Helder Vasconcelos

Вот как я его использую:

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

Твой это:

 @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"); } }); }