Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specifics on using Looper.prepare() in Android

I'm having a bit of trouble understanding how to use the Looper prepare()/loop()/quit() logic.

I have three threads: one is the UI thread, one is a game logic thread and the last is a network communication thread (a background thread, lives only while being used).

The game thread has many dependencies on the results of the network calls, so I wanted to spin the network thread off of the game thread and have a Handler post the result back.

Of course, since the UI thread is not involved I need to call Looper.prepare()... somewhere. I thought it should be called in the game thread, but I can't do that because loop() takes it over.

How do I go about posting back to the game thread from network thread with my handler?

like image 661
atheaos Avatar asked Jul 13 '11 03:07

atheaos


People also ask

What does Looper prepare do?

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

How does Looper work android?

What is Looper? Looper is a class which is used to execute the Messages(Runnables) in a queue. Normal threads have no such queue, e.g. simple thread does not have any queue. It executes once and after method execution finishes, the thread will not run another Message(Runnable).

What is Looper and handler in Android?

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.

How many loopers and handlers can be attached to a thread?

Looper loops through a message queue and sends messages to corresponding threads to process. There will be only one unique looper per thread. That means only one MessageQueue per thread. There can be any number of handlers for one single thread.


1 Answers

What's going on is that once you call Looper.prepare() followed by Looper.loop() on a Thread, all that Thread will ever do is service its MessageQueue until someone calls quit() on its Looper.

The other thing to realize is that, by default, when a Handler is instantiated, it's code will always execute on the Thread it was created on

What you should do is create a new Thread and in run() call Looper.prepare(), setup any Handlers, and then call Looper.loop().

Bearing these things in mind here is the basic pattern I use a lot of places. Also, there's a good chance you should just be using AsyncTask instead.

public class NetworkThread extends Thread {
    private Handler mHandler;
    private Handler mCallback;
    private int QUIT = 0;
    private int DOWNLOAD_FILE = 1;
    public NetworkThread(Handler onDownloaded) {
        mCallback = onDownloaded;
    }

    public void run() {
        Looper.prepare();
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    // things that this thread should do
                    case QUIT:
                        Looper.myLooper().quit();
                        break;
                    case DOWNLOAD_FILE:
                        // download the file
                        mCallback.sendMessage(/*result is ready*/);
                }
            }
        }
        Looper.loop();
    }

    public void stopWorking() {
        // construct message to send to mHandler that causes it to call 
        // Looper.myLooper().quit
    }

    public void downloadFile(String url) {
        // construct a message to send to mHandler that will cause it to
        // download the file
    }
}
like image 96
cyngus Avatar answered Oct 31 '22 21:10

cyngus