Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm trying to use the UI-Thread, so I've written a simple test activity. But I think I've misunderstood something, because on clicking the button - the app does not respond anymore

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();
                Didn't this be Garbage collected almost immediately? Probably you need to keep some reference to the Thread()
– Nick
                Jun 21, 2013 at 17:38
                @Nick: the garbage collector watches also the stack, i.e. when the thread is running, it wont get GC'ed.
– Miro Kropacek
                Mar 13, 2016 at 19:45
                @Vipul, I had a question about phone rotation: I want once I rotate my phone this thread runs and no new thread gets created. Can you provide some hints on how to prevent creation of new thread once the phone is rotated?
– user1836957
                Feb 27, 2018 at 20:01

Just wrap it as a function, then call this function from your background thread.

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

You have it back-to-front. Your button click results in a call to runOnUiThread(), but this isn't needed, since the click handler is already running on the UI thread. Then, your code in runOnUiThread() is launching a new background thread, where you try to do UI operations, which then fail.

Instead, just launch the background thread directly from your click handler. Then, wrap the calls to btn.setText() inside a call to runOnUiThread().

While it's true that the click handler is already in the UI thread, a call to runOnUiThread() is unnecessary but it should be harmless. The Javadoc for that method says "Runs the specified action on the UI thread. If the current thread is the UI thread, then the action is executed immediately. If the current thread is not the UI thread, the action is posted to the event queue of the UI thread." – k2col Oct 4, 2017 at 19:21

There are several techniques using of runOnUiThread(), lets see all

This is my main thread (UI thread) called AndroidBasicThreadActivity and I'm going to update it from a worker thread in various ways -

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.) By passing Activity's instance as an argument on worker thread

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.) By using View's post(Runnable runnable) method in worker thread

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.) By using Handler class from android.os package If we don't have the context (this/ getApplicationContext()) or Activity's instance (AndroidBasicThreadActivity.this) then we have to use Handler class as below -

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.");
                Thank you.. Instead of just repeating about runOnUIThread of activity, you have mentioned all possible ways of invoking it..
– Arundale Ramanathan
                Apr 6, 2019 at 12:46
                Thank you.. Instead of just repeating about runOnUIThread of activity, you have mentioned all possible ways of invoking it..
– Arundale Ramanathan
                Apr 6, 2019 at 12:46
                Actually Android Studio will suggest using this lambda version. There is no need to write run method and no @Override.
– eos1d3
                yesterday

We use Worker Thread to make Apps smoother and avoid ANR's. We may need to update UI after the heavy process in worker Tread. The UI can only be updated from UI Thread. In such cases, we use Handler or runOnUiThread both have a Runnable run method that executes in UI Thread. The onClick method runs in UI thread so don't need to use runOnUiThread here.

Using Kotlin

While in Activity,

this.runOnUiThread {
      // Do stuff

From Fragment,

activity?.runOnUiThread {
      // Do stuff

Using Java,

this.runOnUiThread(new Runnable() {
     void run() {
         // Do stuff
@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");

You can use from this sample :

In the following example, we are going to use this facility to publish the result from a synonym search that was processed by a background thread.

To accomplish the goal during the OnCreate activity callback, we will set up onClickListener to run searchTask on a created thread.

When the user clicks on the Search button, we will create a Runnable anonymous class that searches for the word typed in R.id.wordEt EditText and starts the thread to execute Runnable.

When the search completes, we will create an instance of Runnable SetSynonymResult to publish the result back on the synonym TextView over the UI thread.

This technique is sometime not the most convenient one, especially when we don't have access to an Activity instance; therefore, in the following chapters, we are going to discuss simpler and cleaner techniques to update the UI from a background computing task.

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

Source :

asynchronous android programming Helder Vasconcelos

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

It's because:

1) the implicit this in your call to runOnUiThread is referring to AsyncTask, not your fragment.

2) Fragment doesn't have runOnUiThread.

However, Activity does.

Note that Activity just executes the Runnable if you're already on the main thread, otherwise it uses a Handler. You can implement a Handler in your fragment if you don't want to worry about the context of this, it's actually very easy:

// A class instance

private Handler mHandler = new Handler(Looper.getMainLooper());

// anywhere else in your code

mHandler.post(<your runnable>);

// ^ this will always be run on the next run loop on the main thread.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.