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
Multiple Dex Files Define Landroid/Support/V4/Accessibilityservice/Accessibilityserviceinfocompat
How to Hide the Title Bar For an Activity in Xml With Existing Custom Theme
Adding a Library/Jar to an Eclipse Android Project
Start Activity from Service in Android
Android, Detect When Other Apps Are Launched
How to Have Android Service Communicate With Activity
Why Not Use Always Android:Configchanges="Keyboardhidden|Orientation"
Android How to Adjust Layout in Full Screen Mode When Softkeyboard Is Visible
How to Resize a Bitmap in Android
Custom Adapter Getview() Method Is Not Called
How to Make Layout With Rounded Corners..
Can't Find Theme.Appcompat.Light For New Android Actionbar Support
Getviewtypecount and Getitemviewtype Methods of Arrayadapter