Thursday, February 17, 2011

Android : Passing data between main thread and worker threads.

There may be situations where you want to spawn a thread from your Activity or Service to handle long running (and may be blocking) tasks. In such cases, its sometimes necessary to pass data back and forth between the main thread and the worker thread(s). E.g. if the worker thread finishes a task and returns the result to the main activity to display the results OR you want to keep a worker thread around and ask it to switch between tasks depending on some message you pass to it.

In the past, I faced some problems understanding these concepts associated with different classes in android.os like the Handler, Looper, HandlerThread etc...

I'll try to explain these concepts in a simple language. Probably most of these explanations are from the developer documentation, but I thought consolidating these at one place may help to get a good picture.

Ok. So, when an application runs, it runs in a Main thread called as the UI thread. Any other thread can be created using the standard java.lang.Thread class. As I said in a typical situation you will spawn a thread, may be pass some data to it OR the thread may pass back some data to the Main thread from time to time as well as when its done executing.

Let us consider the task where we need to send data to a worker thread. So first, we create a worker thread.

STEP 1: Create a worker thread

class MyThread extends Thread {
    @Override
    public void run(){
    }
}

In our main thread...

MyThread mThread = new MyThread();
mThread.start();

When you have to pass any messages to a thread or get messages from a thread, the receiving thread needs a MessageQueue. By default, a thread created by using the java.lang.Thread class will not have a MessageQueue associated with it. Its just a plain old thread as in the Fig. 1 (Yes, I know. What an innovative diagram !! :D ).




Now, we need to attach a MessageQueue to our thread. The Looper class provides the method prepare() to create a message queue for a thread. We need to call this method from the receiving thread's run method.


STEP 2: Call the Looper methods


class MyThread extends Thread {
    @Override
    public void run(){
           Looper.prepare();
           Looper.loop();
    }
}



As you see, there is one more Looper method called in the code. This loop() method will start running the message loop for the current thread. In simple terms, it will start looking at the MessageQueue and processing the messages. This is how I interpret the Looper as in Fig. 2.



But, who sends the messages to the MessageQueue and how are these processed ? There is a class called the Handler. The Hander allows us to send and process Messages (as well as Runnable Objects) associated with the thread's MessageQueue. So, we need to create a Handler. It is important to note that the Handler is associated with the thread that creates it ! The Handler provides methods to handle (receive) Messages as well as send and schedule messages. For details, please refer to documentation.



STEP 3: Create a Handler to receive the Messages

class MyThread extends Thread {
    public Handler mHandler;

    @Override
    public void run(){
           Looper.prepare();

           mHandler = new Handler() {
                   public void handleMessage(Message msg) {
                       // Act on the message
                   }
           };
           Looper.loop();
    }
}

If you notice, this code is the same that is listed on the Looper documentation page here.  Few things to mention here are. The Handler is created in this thread, hence it is associated with the default Looper (read MessageQueue) in the current thread. There are constructors for the Handler that allow us to specify the Looper (again, read MessageQueue). This allows us to write a cleaner code by writing the Handler class separately and passing on a Looper (again, again, read MessageQueue) when the Handler is created. I'll get to this in a while. But as I have insisted, it is worth noting that whenever the developer documentation refers to a Looper, you can assume they are talking about a queue. I'm really not sure why they have surfaced the Looper class. It creates more confusion (at least for me). Also, when dealing with passing the messages, with this mechanism, we really need not care of the MessageQueue call. That is the reason I haven't linked it to the documentation. Anyways... things are what they are ! For me, I like to interpret this whole mechanism as depicted in Fig. 3.


Let me know if you like PAT or your way of viewing it !

So, now any other thread having the reference to mHandler will be able to call the send or post methods of the Handler class to send a Message (or a runnable object) to our thread. The code for sending message will look like:

Message msg = Message.obtain();
msg.obj =  // Some Arbitrary object
mHandler.sendMessage(msg);

Pretty simple yeah ! Btw, there are various methods to set/get data for the Message object which can be found in the developer documentation for the Message class.

Summary of Steps :
1. Create a Handler in the receiving thread [If it is the main thread, create one in the main thread]. By default the handler will be associated with the default queue (Looper).
2. So, if the receiving thread is created by using java.lang.Thread, then we need to call the Looper.prepare() and Looper.loop() in order to set up the message queue for the thread.
3.  In the sending thread, prepare a message object (or a Runnable object)
4. Get a reference to the Handler in the sending thread and call the send/post methods on it to send a message.

HandlerThread:
Since by default java.lang.Thread doesn't contain a message queue (Looper), Android provides a class called as the HandlerThread which already contains a message queue. The only difference in using the HandlerThread class over the method described above is that you need not call the Looper.* methods.

On creation of a HandlerThread, Android will create a thread containing the looper. So, in the main thread the code will look like:

HandlerThread myThread = new HandlerThread("Worker Thread");  
myThread.start(); 

We separately create a Handler as follows:

class MyHandler extends Handler { 
    public MyHandler(Looper myLooper) { 
        super(myLooper);
    }
    public void handleMessage(Message msg) { 
    }

Now in the main thread, we get the looper for the HandlerThread and pass it when we create the Handler as follows:

Looper mLooper = myThread.getLooper(); 
MyHandler mHandler = new MyHandler(mLooper); 

Whenever we want to send a message from the main thread, we do it in a similar fashion.

Message msg = mHandler.obtainMessage(); 


msg.obj =  // Some Arbitrary object
mHandler.sendMessage(msg); 


I like to visualize this as shown below in Fig. 4 where we write the Handler separately and then pass a looper to it on its creation.





57 comments:

  1. Thank you very much!
    Threads are one of throes things there doesn’t appear a lot of (helpful) information on and inter-tread communication is one of throes key things people assume you know.
    Anyway I’ve got a couple of quick questions I hope you can help me with.
    Firstly, at the foot of your post when you talk about the UI thread getting the looper for the worker thread you has the following code :-
    Looper mLooper = myThread.getLooper();
    MyHandler mHandler = new MyHandler(mServiceLooper);
    Should that be:
    Looper mLooper = myThread.getLooper();
    MyHandler mHandler = new MyHandler(mLooper);
    Or is mServiceLooper declared somewhere else and I’ve missed it?
    Secondly am I correct in assuming worker thread can talk to other worker threads (ones they start) in the same way?

    Thanks again Scott

    ReplyDelete
  2. @Scott Thanks for the comment.
    1. I'm sorry its a typo. Thanks for pointing it out.
    2. Yes, as long as the worker threads have access to the handlers of other threads, they can communicate and this is the preferred mechanism too.
    Hope this helps.

    ReplyDelete
  3. Now don't get me wrong, this is a good article, but I fear it unnecessarily confuses two separate ideas: 1) Threads and 2) the Looper/Handler/MessageQueue implementation build on TOP of Java threads. The presentation might be improved by separating these tow ideas.

    So, for example, is is simply not true to claim that "When you have to pass any messages to a thread or get messages from a thread, the receiving thread needs a MessageQueue." Why, the whole POINT of the distinction between 'threads' and 'processes' is that threads share address space (therefore global variables) while processes do not. So messages can be passed through globals.

    Now of course, globals introduce their own problems, and should be avoided anyway in Object Oriented Programming, whic is what we are usually trying to do in Java in the first place. But I have often seen Android programmers use shared variables like this for very simple message passing. The reader of this article should be prepared for seeing such things too. Even if the article does not recommend imitating such code.

    After all, only the very simplest message passing should be done with shared variables: the MessageQueue should be used for more complicated scenarios.

    ReplyDelete
  4. I hope I am not flooding you with too many comments, but it also occurs to me: no discussion of Threads and threading can be complete without mention of the classic problems of multi-threading, data races, deadlock and starvation. These are mentioned briefly and in slightly different language in Oracle's Java Tutorial (thread on concurrency), and also at http://www.cs.duke/edu/~chase/systems/concurrency.html.

    To be sure, most of these problems can be avoided by using the MessageQueue, but not all. If the programmer is not thinking about it, he can accidentally design a message-passing scheme that is still liable to deadlock, especially with multiple worker threads.

    The classics on these issues, by Birrell and Dijkstra, are still good reading, but their code samples all use pseudo-code based on ancient languages like Modula II and Algol60:( That is why I gave you the Duke University reference instead.

    ReplyDelete
  5. Question: in Step 2, you say, "In simple terms, it [the Looper] will start looking at the MessageQueue and processing the message". Then a little later you say about the Handler that "The Hander allows us to send and process Messages".

    But wait! Now we have message processing mentioned as happening in TWO different places. How can this be correct? Is there a difference between the 'processing' that takes place in the Looper, and that that takes place in the Handler methods?

    This was never clear in the online Android documentation either, so your readers will thank you even more than they already have if you can make it clear;)

    ReplyDelete
    Replies
    1. I guess that the handler's handleMessage will be invoked by the Looper on the receiver thread

      Delete
  6. Thank you for that.
    It was also helpful for me.

    ReplyDelete
  7. Do both the sender and receiver need loopers? Or just the receiver?

    Thanks,

    Chris.

    ReplyDelete
  8. @Chris, you'll need a Looper only retrieve (receive) messages

    ReplyDelete
  9. Great explanation!

    But what if you had an ArrayList that contains custom objects that you have to pass to the main thread?

    Let me give an example: you want to show a list of movies to the user, but this is kind of a big list so you'll use a thread to fetch and load the movies.
    step 1: address your handler to fetch the movies and make an arraylist of movies (an object that you made yourself, with title, cover, ...)
    step 2: returning this list to your UI-thread
    step 3: displaying your movies

    How would you return this list to your UI-thread? And how do you write your movie class? Do you just make a class with properties and no special interfaces to implement or do you have to implement Parcelable and methods or Serializable?

    Thank you in advance :-)
    Niels

    ReplyDelete
  10. @Niels, for such complex data, I would suggest you take a look at the REST API design pattern (http://www.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html). This article is mainly for quick and short data. For a large amount of data like the ArrayList that you want, it would be advisable to cache the data. What if the main thread is stopped by the time the worker thread completes its task ? All the effort of fetching and loading the movies will go waste. You will have to redo everything which will be expensive !

    ReplyDelete
  11. Great explanation but I still need a little help to understand how to use this please.
    In step 3 the data has been passed to mHandler as 'msg'.
    'msg' is a variable in local class mHandler so does not have scope outside mHandler.
    So how do I use the data in 'msg' with the MyThread class?

    Thank you,
    Declan.

    ReplyDelete
  12. THANK YOU!!! I've been searching for some time for a good (in this case, great) explanation. Threads and message queue are finally clear to me. For everything else I can use android docs, but now I understand the principles...

    Cheers!
    Newman

    ReplyDelete
  13. Thank You, nice explanation. I have a very basic question here,
    Iam clear in sending message to the thread created by main, but how to communicate back results to main thread from child ?
    -regards,
    Manju

    ReplyDelete
    Replies
    1. Manja,

      I believe u need to have a separate msg q (read as Looper) and it's handler object in the main.

      --Guru

      Delete
  14. Excellent. Just what I was looking for.
    I wonder how this blog was hidden from me for so many days.

    ReplyDelete
  15. Excellent and extraordinary explanation on the concept of threads and loopers, i am really glad to bookmark this blog......:)

    ReplyDelete
  16. Nice Thread Tutorial, i am new in android , its help me a lot ...

    I have got some good links

    here
    at androidexample.com
    Thread_With_Handlers

    ReplyDelete
  17. Nice Thread Tutorial, i am new in android , its help me a lot ...

    I have got some good links

    here
    at androidexample.com
    Thread_With_Handlers

    ReplyDelete
  18. Thanks for the posting very useful blog. There is a stack overflow post about an issue which can help developer also. Please check this URL http://stackoverflow.com/questions/4838207/how-to-create-a-looper-thread-then-send-it-a-message-immediately.

    ReplyDelete
  19. Thanks a lot for posting this post, Your post has always been an informative source for me.
    android training

    ReplyDelete
  20. I am reading your post from the beginning, it was so interesting to read & I feel thanks to you for posting such a good blog, keep updates regularly..
    Android Training Institute in Noida
    Dot Net Training Institute in Noida

    ReplyDelete


  21. Thanks for sharing this valuable information and we collected some information from this blog.
    Android Training in Noida

    ReplyDelete
  22. Thanks for writting such informative articles to help us Noobs :)

    ReplyDelete
  23. i use the many android mobiles but the HONOR 9C is the best all time and that is provide the best user experience.

    ReplyDelete
  24. Ok so this doesn't seem to work for me. If I create a handler(handler 1) inside of a worker thread and then create a worker thread(2) and try to write to the first handler I can't access it unless I create a new instance of the thread. Is there not a way to send data to a worker thread without restarting it? I'm lost. Is this a job for Broadcast Receiver? I can't stop and restart my socket connection everytime I want to send it data from my bluetooth connection. How do you access the handler created inside the thread from outside of the thread or from a thread created under it?

    ReplyDelete

  25. Iam so thrilled because of finding your alluring website here.Actually i was searching for Android.Your blog is so astounding and informative too..Iam very happy to find such a creative blog. Iam also find another one by mistake while am searching the same topicIOS Development.Thank you soo much..

    ReplyDelete
  26. You have explained the topic very nice. Thanks for sharing a nice article.Visit Nice Java Tutorials

    ReplyDelete
  27. Thank you for sharing this wonderful information about Multithreading in Android . Thanks Admin for sharing.

    ReplyDelete
  28. Nagaqq Yang Merupakan Agen Bandarq terbaik , Domino 99, Dan Bandar Poker Online Terpercaya di asia hadir untuk anda semua dengan permainan permainan menarik dan bonus menarik untuk anda semua

    Bonus yang diberikan NagaQQ :
    * Bonus rollingan 0.5%,setiap senin di bagikannya
    * Bonus Refferal 10% + 10%,seumur hidup
    * Bonus Jackpot, yang dapat anda dapatkan dengan mudah
    * Minimal Depo 15.000
    * Minimal WD 20.000
    * Deposit via Pulsa TELKOMSEL
    * 6 JENIS BANK ( BCA , BNI, BRI , MANDIRI , CIMB , DANAMON )

    Memegang Gelar atau title sebagai AGEN POKER ONLINE Terbaik di masanya

    11 Games Yang di Hadirkan NagaQQ :
    * Poker Online
    * BandarQ
    * Domino99
    * Bandar Poker
    * Bandar66
    * Sakong
    * Capsa Susun
    * AduQ
    * Perang Bacarrat
    * Perang Dadu
    * BD QQ (New Game)


    Info Lebih lanjut Kunjungi :
    Website : NAGAQQ
    Facebook : NagaQQ official
    WHATSAPP : +855977509035
    Line : Cs_nagaQQ
    TELEGRAM :+855967014811


    ReplyDelete
  29. I want to to thank you for this good read!! I definitely enjoyed every little bit of it. I’ve got you book-marked to look at new stuff you post. 토토사이트

    ReplyDelete
  30. It’s a very easy on the eyes which makes it much more pleasant for me to come here and visit more often.
    marsbahis
    trendbet
    galabet

    ReplyDelete
  31. Thank you for sharing such detailed Blog. I am learning a lot from you. Visit my website to get best Information About Best IAS Coaching in Ranchi
    Best IAS Coaching in Ranchi
    Top IAS Coaching in Ranchi

    ReplyDelete
  32. bulk whatsapp sender software provides various features like Unlimited Messages sending, Multi-multimedia message sending, Numbers Filters, Groups Contacts Grabber, Anti Block Module, Sleep Control, Speed control, delay control etc. with In built Google Map Extractor And Just Dial Extractor.
    ➡ Our Services:
    ✅ Website Design & Development
    ✅ Software Development
    ✅ Mobile App Development
    ✅ CRM / ERP Development
    ✅ Digital Marketing
    ✅ SEO / SEM / SMM / ASO
    ✅ Paid Promotion
    ✅ Graphics & Design
    ☎ +91 99132 99806 | +91 99132 99862

    ReplyDelete
  33. Cambridge English Academy gives you the best online ielts coaching in laxmi nagar by highly educated teachers so that you can fulfill your dream of going Abroad In which you also get study material, notes, and extra classes along with the course, for which you do not have to pay any extra charge and contact to go or take a demo
    website = https://www.cambridgeenglish.org.in/
    call = 9311441524

    ReplyDelete
  34. Use Bulk whatsApp Sender to Reach your customers at Lighting Speed with Whatso.
    Features:
    Grab Contacts from WhatsApp Groups, Fast sending mode, Schedule Sending & Numbers Filter.

    ReplyDelete
  35. thanks for the information.. Matlab Training in Chennai at login360 centers around Matlab as one of the main specialized programming dialects and abilities today.

    ReplyDelete
  36. 전주출장샵
    Media Foster is the best SEO company who is known for providing result-oriented white hat & best SEO services at Mohali for all businesses. if you need more information visit our website.김제출장샵
    광양출장샵
    나주출장샵
    목포출장샵
    순천출장샵
    여수출장샵

    ReplyDelete
  37. Vcare Technical Institute has been providing students with a rich and diverse learning environment. Our unparalleled teaching methods help to launch students into the successful future they have always dreamed of. Vcare Technical Institute is located in Laxmi Nagar, Delhi and has over 100 students and a renowned staff. We encourage both staff and students alike to grow, learn and create each passing day.

    We are Provided Various Computer Courses Such as Computer Basic With Advanced, Core java, Advance java, Core PHP, Advance PHP++, Photoshop, Computer Typing and Other Courses. A Computer Course Overview Windows 7 overview, MS Word, MS Excel, MS Power Point, MS Publisher, MS Picture Manager, MS Outlook, MS Access, Basic HTML,
    C++ training laxmi nagar Coding classes in Laxminagar , Internet- Search Engines, Email – Account creation, sending and receiving emails, Printing, Scanning, using external Media etc. Excel – creating spreadsheet, Applying formula, pivot table, H lookup, V lookup, filter, freeze, sorting, logical function.

    ReplyDelete
  38. Park View City Lahore is an affordable housing society in Lahore. To get more information about park view lahore check the payment plan.

    ReplyDelete
  39. Park View City Islamabad Overseas Block contains 5 Marla, 10 Marla, and 1 Kanal residential plot to cater to the ex-pats. We all know that every society builds an overseas block to provide amenities and features at international standards.

    The concerned authorities have not revealed the Park View Society Overseas Block location. But according to the sources, it will be announced on 15 July 2022. In addition, it will be situated near the gate, close to the PVC commercial block.

    The PVC Islamabad overseas block will have all the facilities, including health, entertainment, and educational institutes, for visitors through a separate gate.

    Furthermore, the residents of this block will get a 25% discount on medical and educational charges. The overseas block will also provide Free WI-FI across the area.

    ReplyDelete
  40. WhatsApp is one of the most popular messaging apps worldwide, with over two billion users. While it is a powerful tool for personal and business communication, some individuals and organizations have explored the idea of using bulk WhatsApp sender software to send messages to large groups of people simultaneously. In this blog post, we'll discuss what bulk WhatsApp sender software is, its potential risks and benefits, and the ethical considerations that should guide its use.

    ReplyDelete
  41. Growby provides WhatsApp marketing software. Your marketing game will get enhanced 10 times. Moreover, your revenue will increase almost effortlessly.

    You can visit here to know more about this software: https://www.growby.net/whatsapp-marketing-software

    ReplyDelete
  42. Having plethora of features, this whatsapp marketing software will effortlessly help you contact your customers via whatsapp. the marketing channel which has a huge user base and is easily accessible by users all around the world

    ReplyDelete
  43. This information is so impressive. Thanks for sharing it.If you are interested in Technical Stuff vist our Site VLSI Training in Bangalore for more info.

    ReplyDelete