Как мы используем 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 122

9 ответов:

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

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

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

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

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

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

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

Это мой основной поток (UI поток) называется 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.) С помощью класса обработчика из 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.");
        }
    });
  }
}

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

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

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

когда пользователь нажимает на кнопку поиска, мы создадим запускаемый анонимный класс, который ищет введенное слово ИД р..полей EditText wordEt и начинается поток для выполнения 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");


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

    }