Reputation: 2836
I read that the Android Handler can be used to communicate with the main Looper thread to post messages that will interact with the views(since only main thread can interact with views there)
But I often see code like the example below that run the Handler in the main thread. Why is that a good think to do, it feels unnecessary unless there is a delay like postDelayed(new Runnable()...
Any explanation on this would bee nice
public class TaleDemoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
new Handler().post(new Runnable() {
@Override
public void run() {
new Handler().post(new Runnable() {
@Override
public void run() {
new Tale("Hello runnables!").tell();
}
});
new Handler().post(new Runnable() {
@Override
public void run() {
new Tale("Hello runnables!").at().tell();
}
});
}
});
new Handler().post(new TestRunnable());
new Handler().post(new TestStaticRunnable());
new Handler().post(new TestAbstractRunnable() {
@Override
public void run() {
new Tale("Hello abstract runnable!").tell();
}
});
new Handler().post(new TestInterfaceRunnable() {
@Override
public void run() {
new Tale("Hello test interface runnable!").tell();
}
});
new Tale().at().tell();
}
class TestRunnable implements Runnable {
@Override
public void run() {
new Tale("Hello testRunnable!").tell();
}
}
static class TestStaticRunnable implements Runnable {
@Override
public void run() {
new Tale("Hello testStaticRunnable!").tell();
}
}
abstract class TestAbstractRunnable implements Runnable {
}
interface TestInterfaceRunnable extends Runnable {
}
}
Upvotes: 1
Views: 3393
Reputation: 14183
Handler is not used just to communicate with the main Looper.
Looper
is a class that loops over a queue of messages and dispatches them, each instance works with one Thread
.
A HandlerThread
is a Thread
that also has a Looper
attached to it.
The "main" Thread
of your application is also a HandlerThread
.
When you instantiate a Handler
with the empty constructor, the Handler
will be attached to the Looper
of the Thread
in which you are creating the instance. If, for instance, you create a Thread
in onCreate
of an Activity
, then the Handler
will be attached to the main (UI) Thread
because the lifecycle callbacks are executed there.
When you call post(Runnable)
, the Runnable
will be run on the thread the Handler
's Looper
is attached to. So, if you create a Handler
in one of the lifecycle callbacks of your Activity
, then no matter which Thread
you post the Runnable
from, it will always be executed on the main Thread
This is the most common usage and it is what your code does, but it's not the only one. For instance you could instantiate a HandlerThread
, then from the Activity
lifecycle callbacks you could post a Runnable
that performs very long operation and it will not block your UI because it will be executed on a different Thread
.
Another usage of post(Runnable)
(and sometimes a universal dirty fix for weird UI bugs) is to call it from the main thread just with the purpose of delaying the execution until after the whole method had been executed.
fun onCreate(savedInstanceState: Bundle?) {
Handler().post {
// code here is executed after `onCreate` has returned
}
// code here is executed before the one posted on the Handler
}
Upvotes: 5