I had to add Looper to the following code:
public class MyRunnable implements Runnable
{
@Override
public void run()
{
Looper.prepare();
final Looper looper = Looper.myLooper();
new Handler().postDelayed(
new Runnable()
{
@Override
public void run()
{
try
{
}
catch (Exception ex)
{
}
finally
{
looper.quit();
}
}
}, 100);
Looper.loop();
}
}
Notice that I have a runnable inside a runnable. The nested runnable gets executed through a Handler. Initially I didn't have Looper but Android complained that I needed to call Looper.prepare before executing another thread.
I read up on Looper but it still seems kind of cryptic. It seems to act like some kind of internal messaging pipeline. It isn't clear to me why this is necessary since there are no messages going from my outer runnable to my inner runnable. Even though that is true, it seems that Android just makes the hard rule that if you call a thread from a thread, you MUST also call Looper.prepare. Even if I accept that as-is, it still doesn't help to understand why I need to call looper.loop and looper.quit. If I omit Looper.loop, my Handler never runs and that is what isn't clear. What does Looper.loop do that allows my Handler to run?
Looper is an abstraction over event loop (infinite loop which drains queue with events) and Handler is an abstraction to put/remove events into/from queue with events (which is drained by Looper) and handle these events when they are processed.
It is a kind of worker that serves a MessageQueue for the current thread. Looper loops through a message queue and sends messages to corresponding threads to process. We can retrieve the MessageQueue for the current thread with Looper. myQueue() .
All of the artifacts involved in the build process are typically retained in the repository.
Runnable is an interface which used for creating a new thread class similar to the thread class created by extending java. lang. Thread class. Only difference is, Runnable interface allows the class to extend other class (if required) to override/inherit functionality of some class.
Here is a great article about that.
Looper and Handler in Android
It comes along with a simple schema that leads to straight understanding of relationship between Loopers and Handler.
On this schema, we see that, within the same thread (depicted by the big rectangle), no matter how many handler you create, they will all be using the same Looper, i.e., the unique looper of this thread.
Note:
Looper have to be prepared to allow associated handler to process posted messages.
Android application, more precisely, android app UI thread(the main thread), already comes with a prepared looper (the mainLooper).
Here is how to Communicating with the UI Thread.
A simple concept of the looper:
Every worker thread you create and run ends once it performs its last operation.
To prevent your thread termination you can start a loop by calling Looper.loop()
, think of it as while(true){}
statement. Before calling Looper.loop()
you have to prepare the loop with Looper.prepare()
, if it is not prepared yet.
To terminate the loop and end your thread you will need to call looper.quit()
on the looper.
Now for the notification you got from Android:
When you create a Handler in a thread, it will be bound to the thread it is created in and when you post runnable using this Handler, the code runs on the thread of the Handler.
So when the system saw that you want to run some code (especially 100ms in future) on a Handler that is bound to a thread that is going to die as soon as it finishes calling the post method it proposed to use Looper.loop()
to prevent this thread from terminating and thus enabling you properly run the second Runnable in a still existing thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With