Handler in Android Project : Thread Safe - android

I am using Handler in an android project to give a callback to to the main/ui thread.
if (mHandler == null) {
mHandler = new Handler(Looper.getMainLooper());
}
mHandler.post(new Runnable() {
public void run() {
freeBeePlaybackEventListener.onError(freeBeeError);
}
});
When I am creating the handler object i.e. mHandler , I am checking whether the handler already exists or not. If not, then I am creating the handler i.e. using a singleton pattern. My question is: Is creation of the handler object thread safe ?
Thanks.

No, this code is not thread safe.
But the problem is not the Handler itself but the creation pattern used.
If the code that you reported here is called at the same time by two different thread, it may happen a critical race where two different Objects (in this case Handler) are created.
If you are sure that this code is called always by the same thread, you can safely use it.
By the way, this is the same problem of the lazy Singleton creation, and it is usually solved in this way:
if( mHandler == null )
{
syncronized( this )
{
if( mHandler == null )
mHandler = new Handler(Looper.getMainLooper());
}
}
Where 'this' is a synchronizing object that may be the class container or anything else.

Handles are Thread Safe.
To handle more complex interactions with a worker thread, you might consider using a Handler in your worker thread, to process messages delivered from the UI thread. (DOC-Worker Threads)
Normally, you create a Handler for a new thread, but you can also create a Handler that's connected to an existing thread. When you connect a Handler to your UI thread, the code that handles messages runs on the UI thread (Android Documetation)

Related

What are Handlers and Runnables for in Android?

Please I am blocked with this concept of Handlers and Runnables in Android. Can someone please give me detailed explanation on Handlers and Runnables? Their syntax and implementation? I have read many articles on this but the concepts are not still clear and are even deployed in Java. Thanks in advance
I'm going to try to simplify so bear with me if it is not 100% accurate.
Basically, a Handler is used to communicate with a MessageQueue associated with a Thread.
If you're on the main thread, or if you've called Looper.prepare() in the Thread that you're in, it has a Looper which is basically a holder for the MessageQueue.
This queue is constantly polled so that whenever a Message goes into it, it's dealt with on the Thread associated with this MessageQueue
If you're trying to execute a piece of code on a particular Thread, you have to use a Runnable. It is just an interface that has a void run() method which will be executed by the Looper, on its Thread.
Let's say you're doing a network request, you want it to happen on another Thread but when you get the result you somehow need to pass the data back to the Main Thread in order to update your UI because Views can't be modified from another Thread.
You would do it like so:
// This will let you run method on main thread (even if you're not on main thread)
private final Handler handler = new Handler(Looper.getMainLooper());
// This will let you run method on background thread
private final Executor executor = Executors.newSingleThreadExecutor();
public void doSomething() {
// posting to executor will go to background thread
executor.post(new Runnable() {
#Override
public void run() {
// This will now run on background thread
// you can for example do network request here
// posting to handler will go back to main thread
handler.post(new Runnable() {
#Override
public void run() {
// This will execute on the Main Thread
}
});
}
});
}

Usage of a handler

I'm recently getting involved in some concurrent programming specially with Java and Android.
I have some questions regarding Handlers.
1 - It is known that we need to associate a Handler with a thread, and it will run on the thread it was invoked on. However, in some examples on SO, the user is doing
public class MainActivity extends Activity
{
private Handler handler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState)
{
handler.postDelayed(runnable, 1000);
}
private Runnable runnable = new Runnable()
{
public void run()
{
//Do whatever
handler.postDelayed(this, 30000);
}
};
In this example, I assume we are doing the Handler thing on the UI Thread, RIGHT ?
Can I do a network operation here in place of //DO Whatever ? I don't think so, because we are on the main thread.
Is doing this pointless ? As one may use AsyncTask to replace this task ?
How can I apply this same example but not on the UI thread, rather a seperate thread ?
Do thread or Runnables have something similar to post delayed ?
Is it common to use the handler just for its postdelayed feature and not the main task handlers are made for, ie, being the middle man between the thread and the UI/Activity ?
Handlers are useful only when you want update UI. As you may know we cannot update UI from non UI Thread. If you are going to do some network stuff in background thread, and then update UI, you have to use Handler class or AsyncTask or you can do like this:
(from non UI Thread)
SomeView.post(new Runnable() {
//updating UI
});
If whatever you are doing is "heavy" you should be doing it in a Thread. If you do not explicitly start it in its own thread, then it will run on the main (UI) thread which may be noticeable as jittery or slow to respond interface by your users.
Interestingly when you are using a thread it is often useful to also use a Handler as a means of communication between the work thread that you are starting and the main thread.
A typical Thread/Handler interaction might look something like this:
Handler h = new Handler(){
#Override
public void handleMessage(Message msg){
if(msg.what == 0){
updateUI();
}else{
showErrorDialog();
}
}};
Thread t = new Thread() {
#Override
public void run(){
doSomeWork();
if(succeed){
//we can't update the UI from here so we'll signal our handler and it will do it for us.
h.sendEmptyMessage(0);
}else{
h.sendEmptyMessage(1);
}
} };
In general though, the take home is that you should use a Thread any time you are doing some work that could be long running or very intensive (i.e. anything network, file IO, heavy arithmatic, etc).

How the Looper knows to send the message to Handler?

The question is, where I tell my Thread to use mHandler for the Looper?
Thank you.
I am using the below code:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
The question is, where I tell my Thread to use mHandler for the
Looper?
You don't need to tell it explicitly, because the system (framework) does it for you. When you instantiate the Handler, it will automatically obtain access to the message queue of your current Thread. Quoting your comment:
How the system know to send the message to the mHandler Handler?
I'll detail it below.
This is the constructor of android.os.Handler in Android:
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
As you can see, first it obtains the Looper of your current Thread. The source code of Looper.myLooper() is as follows:
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
It obtains it from the thread local storage. Later, when you send a Message with this Handler, the Handler actually sets itself as the recipient of the Message: this is how the Looper will know where to dispatch the Message when it arrives. In details:
When you call mHandler.sendMessage(), eventually this code runs (among many other code lines):
MessageQueue queue = mQueue;
boolean sent = false;
if (queue != null) {
msg.target = this; // msg is your Message instance
sent = queue.enqueueMessage(msg, uptimeMillis);
}
As you can see, it sets the Handler instance as the target of the Message. So, later, when the Message is dispatched, it will contain the Handler as its target. This is how the Looper will know which Handler it should dispatch it to. In details, when you call Looper.loop(), the following happens for each of your Message instances in the queue:
msg.target.dispatchMessage(msg);
The dispatchMessage() code is the following:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
Notice the last handleMessage(msg) call -- this is exactly your handleMessage(msg) override!
To have a better understanding, create a normal Thread and try creating a Handler in the run() method of that thread. You'll get a RuntimeException saying:
Can't create handler inside thread that has not called
Looper.prepare()
Now calling Looper.prepare() in the run() method before creating a Handler would create a new Looper object associated with the calling thread. The source of your confusion is that Looper.prepare() does not take a Thread as argument. It need not, since it's a static method, which internally gets the ThreadLocal of the currently running thread. There can be at most one Looper associated with any Thread.
Now, calling new Handler() would associate the new Handler object with the Looper of the current Thread by internally calling Looper.myLooper(). You can create more than one Handler each with its own Callback in the same Thread. All Handlers would get their messages from the message queue of the same Looper.
You don't tell anything. From the Handler documentation:
Each Handler instance is associated with a single thread and that
thread's message queue. When you create a new Handler, it is bound to
the thread / message queue of the thread that is creating it - from
that point on, it will deliver messages and runnables to that message
queue and execute them as they come out of the message queue.
The handler is automatically bound to the thread's message queue. You only implement the callback, and the system will take care of everything, ie dispatching and processing the messages. Actually I agree that, using two static methods like Looper.prepare() and Looper.loop() and automatically infer things, makes the pattern feels like black magic :)

Confused with threading - Handler blocks UI thread

I have a time consuming task (iterating through files and sending it's content to server) that I want to execute in background thread, in specific interwal (that's why I want to use Handler).
From UI thread I have a call like this:
LogsManager lm;
lm = new LogsManager(this);
lm.processLogFiles();
And in LogsManager class I have following piece of code:
public void processLogFiles(){
Handler mHandler = new Handler();
mHandler.postDelayed(logsRunable, 1000);
}
private Runnable logsRunable = new Runnable() {
#Override
public void run() {
File f = new File(Environment.getExternalStorageDirectory()+Constants.LOG_DIR);
File[] logFiles = f.listFiles();
for (int i = 0; i < logFiles.length; i++) {
readLogs(logFiles[i]); // executes some other methods inside
}
}
};
As you can see it's just method with Handler that calls Runnable. And, unfortunately it also blocks my UI thread. Isn't Handler supposed to start a new thread for Runnable? I use handlers in other parts of my app also, and they works just fine. Am I'm doing something wrong?
As stated in the docs, Handler:
When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it
So if you're creating mHandler in UI thread, then it will run the tasks in UI thread - hence the problem.
All the post* methods in Handler run code on Handler's original thread (in your case the GUI thread). If you want a background thread, you need to explicitly start one (see below) or use AsyncTask, if you need to update the GUI.
Thread t = new Thread(logsRunable);
t.start();
I think you should use AsyncTask class for this purpose.
Scheduled the execution for the task after a specific delay, in your case it is 1000.
I also think AsyncTask is a good solution for your case.

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?
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
}
}
Could you tell some examples for what you are using your network thread? I think you can solve your problems without using Looper.
You can use ASyncTask to perform background task that may update some values in your UI thread. If user has to wait until background operation will be finished, you can show ProgressDialog and block application in OnPreExecute method, and then hide it in onPostExecute.
As I said, please describe more your needs and target which you want to achieve.

Categories

Resources