Android Basics: Running Code in the Ui Thread

Android basics: running code in the UI thread

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().

Basics: Running code in main thread

The timing is different. In the first snippet the code is executed as part of the onCreate execution so it is guaranteed to finish before onCreate returns, in the second snippet, it is executed some time later (maybe after several other callbacks).

Running a method on UI thread

If you're calling the same UI method repeatedly, you could streamline the client code by creating the Runnable in a method:

private void updateUi(final String message) {
runOnUiThread(new Runnable() {
public void run() {
ui.myMethod(message);
}
});
}

Then your client code would simply call updateUi("changetext"). (This code assumes that ui is final. If not, you could pass in a final reference.)

If you're calling a different UI method every time, this doesn't gain you anything as you'd need a separate update method for each UI method. Your existing code is as elegant as it gets.

How can I find out which parts of my code are using the UI Thread the most?

First thing you can do is enable StrictMode. That will detect non-UI, potentially long operations running on the main thread.

Second thing you can do is profile the CPU, as stated above. You'll be able to see the activity per thread, so you can determine what is running where. In order to get accurate readings, don't run it from Android Studio. Run it directly from your code. The easiest way to do that is to use the Debug class, and start the sampling at the Application.onCreate && finish it when the app closes.

The third thing you can do is to observe the messages sent to the main thread looper and evaluate them. Pierre-Yves Ricau has a nice guide about this that you can adapt to your own processes.

After that, you can use custom approaches to evaluate critical parts of your code, like generating your own traces. Perfetto uses JSON files, so you can print logcat messages from the parts you suspect are causing trouble and parse those messages into a perfetto trace.

Execute in a separate thread

You can use Coroutines to do background work.

 class PacketsLocalDataSource(private val context: Context) {
private val dao: PacketsDao by lazy{PacketsDatabase.getInstance(context).packetDao() }

fun saveLocal(packet: Packet) {
CoroutineScope(Dispatchers.IO).launch {
dao.add(packet)
}
}

Run on UI thread from another class

You can use this snippet

textView.post(new Runnable() {
@Override
public void run() {
textView.setText("Text");
}
});

running a piece of code on separate thread

On further looking into thread part, I managed to find that using ThreadHandler is simpler than using a thread + a looper (as a ThreadHandler has a looper attached to it by default, and manages it well). So, this is the code I am looking towards for now.

HandlerThread mThread = null; 
Handler mHandler = null;
func(){
subA();
if(mThread == null){
mThread = new HandlerThread("mThread");
mThread.start();
mHandler = new Handler(mThread.getLooper());
}
mHandler.post(new Runnable(){
public void run(){
subB();
subC();
}});
}

But I find one issue with this code, I still need to create a new object of a runnable on each call to func(). Need to find out how I can avoid this.

Android: My async task is running on the ui thread and stalling my app

You are calling get() on the AsyncTask. This says "tie up the current thread until the task completes". Since your current thread is the main application thread, you are blocking that thread, which completely eliminates the value of using AsyncTask in the first place.

Remove your get() calls. Use the results of your task in onPostExecute(), which is called on the main application thread, and so it is safe for you to update your UI there.



Related Topics



Leave a reply



Submit