{"id":690,"date":"2011-07-17T22:50:35","date_gmt":"2011-07-18T05:50:35","guid":{"rendered":"http:\/\/wiebe-elsinga.com\/blog\/?p=690"},"modified":"2011-07-17T22:50:35","modified_gmt":"2011-07-18T05:50:35","slug":"handlers-and-asynctasks-android-doing-multithreading","status":"publish","type":"post","link":"http:\/\/wiebe-elsinga.com\/blog\/handlers-and-asynctasks-android-doing-multithreading\/","title":{"rendered":"Handlers and AsyncTasks, Android doing multithreading"},"content":{"rendered":"<div class=\"wpsso-pinterest-pin-it-image\" style=\"display:none !important;\">\n<\/div><!-- .wpsso-pinterest-pin-it-image -->\n\n<p>Multithreading is always tricky. On any platform and in any language, when not implemented properly you will get unexpected behavior sooner or later.<\/p>\n<p>In the process of making an Android application suitable for Honeycomb, a colleague of mine ran into the <em>NetworkOnMainThreadException<\/em>, which is new in Honeycomb. On earlier Android versions, doing heavy operations on the main thread was strongly discouraged, but still possible. Now, the OS is forcing the developer to implement a proper application structure. Which isn&#8217;t a bad thing at all.<\/p>\n<p>So, to solve the <em>NetworkOnMainThreadException<\/em>, network and other heavy operations needed to move to a background thread. Considering the structure of the application, the most logical choice was to use the <em>Handler<\/em> in combination with a <em>Thread<\/em>.<br \/>\n<!--more--><\/p>\n<h4>Basic setup <em>HandlerThread<\/em><\/h4>\n<p>Here is an example:<\/p>\n<div class=\"codecolorer-container java blackboard\" style=\"overflow:auto;white-space:nowrap;width:100%;height:100%;\"><div class=\"java codecolorer\"><span class=\"kw1\">public<\/span> <span class=\"kw1\">class<\/span> MBOutcomeHandlerThread <span class=\"kw1\">extends<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+thread\"><span class=\"kw3\">Thread<\/span><\/a><br \/>\n<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; <span class=\"kw1\">public<\/span> MBOutcomeHandlerThread<span class=\"br0\">&#40;<\/span><a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string\"><span class=\"kw3\">String<\/span><\/a> name<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">super<\/span><span class=\"br0\">&#40;<\/span>name<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; <span class=\"kw1\">private<\/span> MBOutcomeHandler _outcomeHandler<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; @Override<br \/>\n&nbsp; <span class=\"kw1\">public<\/span> <span class=\"kw4\">void<\/span> run<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">try<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; Looper.<span class=\"me1\">prepare<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; _outcomeHandler <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> MBOutcomeHandler<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; Looper.<span class=\"me1\">loop<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">catch<\/span> <span class=\"br0\">&#40;<\/span><a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+throwable\"><span class=\"kw3\">Throwable<\/span><\/a> e<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; Log.<span class=\"me1\">e<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Log&quot;<\/span>, <span class=\"st0\">&quot;Thread stopped due to error&quot;<\/span>, e<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; <span class=\"kw1\">public<\/span> MBOutcomeHandler getOutcomeHandler<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> _outcomeHandler<span class=\"sy0\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p><strong><em>Looper.prepare<\/em><\/strong> creates a new Looper instance for this thread, which then creates a new <em>MessageQueue<\/em> that <em>Handlers<\/em> can use to post messages on.<\/p>\n<p><em>MBOutcomeHandler<\/em> is a subclass of <em>Handler<\/em>, which implements the <strong><em>handleMessage<\/em><\/strong> method. The constructor of the <em>Handler<\/em> class associates with the Looper.<\/p>\n<p><em>Looper.loop<\/em> starts the Looper and keeps the thread alive. The Looper can be stopped by invoking <strong><em>Looper.quit<\/em><\/strong>. This will end run method of the Thread, hence, the Thread is finished.<\/p>\n<p>It is also possible to use the <em>HandlerThread<\/em> class. This class does the Looper setup for you. It doesn&#8217;t really matter which one you choose, as long as you don&#8217;t forget to instantiate the <em>Handler<\/em> inside the run method. When using the <em>HandlerThread<\/em> you must instantiate the <em>Handler<\/em> in the <strong><em>onLooperPrepared<\/em><\/strong> method.<\/p>\n<div class=\"codecolorer-container java blackboard\" style=\"overflow:auto;white-space:nowrap;width:100%;height:100%;\"><div class=\"java codecolorer\"><span class=\"kw1\">public<\/span> <span class=\"kw1\">class<\/span> MBOutcomeHandlerThread <span class=\"kw1\">extends<\/span> HandlerThread<br \/>\n<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; <span class=\"kw1\">private<\/span> MBOutcomeHandler _outcomeHandler<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; <span class=\"kw1\">public<\/span> MBOutcomeHandlerThread<span class=\"br0\">&#40;<\/span><a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string\"><span class=\"kw3\">String<\/span><\/a> name<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">super<\/span><span class=\"br0\">&#40;<\/span>name<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; @Override<br \/>\n&nbsp; <span class=\"kw1\">public<\/span> <span class=\"kw4\">void<\/span> run<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">super<\/span>.<span class=\"me1\">run<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; _outcomeHandler <span class=\"sy0\">=<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; @Override<br \/>\n&nbsp; <span class=\"kw1\">protected<\/span> <span class=\"kw4\">void<\/span> onLooperPrepared<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; _outcomeHandler <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> MBOutcomeHandler<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; <span class=\"kw1\">public<\/span> MBOutcomeHandler getOutcomeHandler<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> _outcomeHandler<span class=\"sy0\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Now that we have a <em>HandlerThread<\/em> running, we can use the <em>Handler<\/em> to send messages to the Looper.<\/p>\n<p>Please be aware, that the <em>HandlerThread<\/em> keeps looping until the quit method is invoked. It doesn&#8217;t really matter if you use the instance of the <em>HandlerThread<\/em>, the <em>Handler<\/em> or the Looper. After the quit method is invoked, the <em>HandlerThread<\/em> is finished and cannot be started again. For example, if the <em>HandlerThread<\/em> has been quit because the Activity was pushed to the background, you need to clean up the <em>HandlerThread<\/em> in an <strong><em>onPause<\/em><\/strong> or <strong><em>onStop<\/em><\/strong>. When the Activity comes to the foreground again, a new <em>HandlerThread<\/em> must be created. Of course, the starting and stopping of the <em>HandlerThread<\/em> depends on what kind of operations are performed in the Handler. Then again, I think it is good practice to do a little clean up, instead of Android doing all the work.<\/p>\n<h4>AsyncTasks<\/h4>\n<p>After the new <em>Handler<\/em> was created, the next problem occurred. After pushing the application to the background and let it come to the foreground again, the application crashed because of the following error: <em>Handler{4062bc78}<\/em> sending message to a <em>Handler<\/em> on a dead thread. Because I was implementing a Handler, I assumed the exception had something to do with the Handler I created. After a lot of searching and debugging, the cause of the exception were the <em>AsyncTasks<\/em> that are used inside the Handler. Then, after reading the documentation of <em>AsyncTask<\/em>, Android is very clear that <em>AsyncTasks<\/em> must be created and started on the UI thread. But, in the process of moving code to the handler, that was overlooked. After creating and starting the <em>AsyncTasks<\/em>, everything worked fine!<\/p>\n<h4>Recap<\/h4>\n<p><em>HandlerThreads<\/em> and <em>Handlers<\/em> are a great way to handle heavy or long during operations on a separate thread. When using <em>AsyncTasks<\/em> in your Handler, make sure that they&#8217;re created on the UI thread. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Multithreading is always tricky. On any platform and in any language, when not implemented properly you will get unexpected behavior sooner or later. In the process of making an Android application suitable for Honeycomb, a colleague of mine ran into the NetworkOnMainThreadException, which is new in Honeycomb. On earlier Android versions, doing heavy operations on the main thread was strongly discouraged, but still possible. Now, the OS is forcing the developer to implement a proper application structure. Which isn&#8217;t a bad thing at all. So, to solve the NetworkOnMainThreadException, network and other heavy operations needed to move to a background thread. Considering the structure of the application, the most logical choice was to use the Handler in combination with a Thread.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[7],"tags":[154,69,56,70,71],"_links":{"self":[{"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/posts\/690"}],"collection":[{"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/comments?post=690"}],"version-history":[{"count":0,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/posts\/690\/revisions"}],"wp:attachment":[{"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/media?parent=690"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/categories?post=690"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/tags?post=690"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}