Luky
Luky

Reputation: 5406

Android basics: running code in the UI thread

In the viewpoint of running code in the UI thread, is there any difference between:

MainActivity.this.runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

or

MainActivity.this.myView.post(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

and

private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
    protected void onPostExecute(Bitmap result) {
        Log.d("UI thread", "I am the UI thread");
    }
}

Upvotes: 504

Views: 340770

Answers (8)

I.Step
I.Step

Reputation: 779

Kotlin version:

Handler(Looper.getMainLooper()).post {
   Toast.makeText(context, "Running on UI(Main) thread.", Toast.LENGTH_LONG).show()
}

Or if you are using Kotlin coroutines: inside coroutine scope add this:

withContext(Dispatchers.Main) {
   Toast.makeText(context, "Running on UI(Main) thread.", Toast.LENGTH_LONG).show()
}

Upvotes: 2

raghu kambaa
raghu kambaa

Reputation: 115

use Handler

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

Upvotes: 8

Ucdemir
Ucdemir

Reputation: 3098

If you need to use in Fragment you should use

private Context context;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.context = context;
    }


    ((MainActivity)context).runOnUiThread(new Runnable() {
        public void run() {
            Log.d("UI thread", "I am the UI thread");
        }
    });

instead of

getActivity().runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

Because There will be null pointer exception in some situation like pager fragment

Upvotes: 13

Dick Lucas
Dick Lucas

Reputation: 12639

As of Android P you can use getMainExecutor():

getMainExecutor().execute(new Runnable() {
  @Override public void run() {
    // Code will run on the main thread
  }
});

From the Android developer docs:

Return an Executor that will run enqueued tasks on the main thread associated with this context. This is the thread used to dispatch calls to application components (activities, services, etc).

From the CommonsBlog:

You can call getMainExecutor() on Context to get an Executor that will execute its jobs on the main application thread. There are other ways of accomplishing this, using Looper and a custom Executor implementation, but this is simpler.

Upvotes: 13

vasart
vasart

Reputation: 6702

There is a fourth way using Handler

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

Upvotes: 65

Joe
Joe

Reputation: 181

The answer by Pomber is acceptable, however I'm not a big fan of creating new objects repeatedly. The best solutions are always the ones that try to mitigate memory hog. Yes, there is auto garbage collection but memory conservation in a mobile device falls within the confines of best practice. The code below updates a TextView in a service.

TextViewUpdater textViewUpdater = new TextViewUpdater();
Handler textViewUpdaterHandler = new Handler(Looper.getMainLooper());
private class TextViewUpdater implements Runnable{
    private String txt;
    @Override
    public void run() {
        searchResultTextView.setText(txt);
    }
    public void setText(String txt){
        this.txt = txt;
    }

}

It can be used from anywhere like this:

textViewUpdater.setText("Hello");
        textViewUpdaterHandler.post(textViewUpdater);

Upvotes: 18

pomber
pomber

Reputation: 23990

I like the one from HPP comment, it can be used anywhere without any parameter:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

Upvotes: 285

CommonsWare
CommonsWare

Reputation: 1007474

None of those are precisely the same, though they will all have the same net effect.

The difference between the first and the second is that if you happen to be on the main application thread when executing the code, the first one (runOnUiThread()) will execute the Runnable immediately. The second one (post()) always puts the Runnable at the end of the event queue, even if you are already on the main application thread.

The third one, assuming you create and execute an instance of BackgroundTask, will waste a lot of time grabbing a thread out of the thread pool, to execute a default no-op doInBackground(), before eventually doing what amounts to a post(). This is by far the least efficient of the three. Use AsyncTask if you actually have work to do in a background thread, not just for the use of onPostExecute().

Upvotes: 320

Related Questions