Как мы используем runOnUiThread в Android?

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

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

9 ответов


ниже исправлен фрагмент


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

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

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

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


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

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

Это мой основной поток (UI thread) называется 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()
    {

        //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.) С помощью метода post(Runnable runnable) представления в worker нить

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.) С помощью класса Handler из android.пакет ОС Если у нас нет контекста (this/ getApplicationContext()) или экземпляра Activity (AndroidBasicThreadActivity.это), то мы должны использовать класс обработчика, как показано ниже -

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

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

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

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

когда пользователь нажимает на кнопку поиска, мы создадим Runnable anonymous класс, который ищет введенное слово ИД р..полей EditText wordEt и начинается поток для выполнения Runnable.

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

этот метод не самый удобный, особенно когда мы не иметь доступ к экземпляру 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");


            }
        });
    }

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

    }