{"id":255431,"date":"2016-03-20T00:45:49","date_gmt":"2016-03-19T16:45:49","guid":{"rendered":"http:\/\/blog.zhenglei.net\/?p=255431"},"modified":"2016-03-20T00:45:49","modified_gmt":"2016-03-19T16:45:49","slug":"handler-and-activitys-life-cycle-take-care-about-orphan-threads","status":"publish","type":"post","link":"https:\/\/blog.zhenglei.net\/?p=255431","title":{"rendered":"Handler and Activity&#8217;s life cycle, take care about orphan threads!!"},"content":{"rendered":"<p><a href=\"http:\/\/android2ee.blogspot.com\/2011\/11\/handler-and-activity-life-cycle-take.html\">http:\/\/android2ee.blogspot.com\/2011\/11\/handler-and-activity-life-cycle-take.html<\/a><\/p>\n<h2><span style=\"color: #ff0000\">Handler and Activity&#8217;s life cycle, take care about orphan threads!!<\/span><\/h2>\n<h2>\n<p><span style=\"color: #ff0000\"> Hello,<\/span><\/h2>\n<p>You have an Activity which uses a Handler. You create your handler and\u00a0overwrite the handleMessage method, you launch the handler\u2019s thread and that\u2019s it for the handler management\u2026 Most of us do such a thing and it\u2019s a huge mistake!!! What happens to your thread when your activity pauses and resumes and worst when it dies and (re)creates?<br \/>\nYou thread becomes an orphan thread !<br \/>\nSo you have written something like that :<\/p>\n<p><strong>(BAD CODE EXAMPLE DO NOT USE)<\/strong><\/p>\n<p>\/**<\/p>\n<p>* The handler<\/p>\n<p>*\/<\/p>\n<p><strong>private<\/strong> <strong>final<\/strong> Handler slowDownDrawingHandler;<\/p>\n<p>\/** Called when the activity is first created. *\/<\/p>\n<p>@Override<\/p>\n<p><strong>public<\/strong> <strong>void<\/strong> <strong>onCreate<\/strong>(Bundle savedInstanceState) {<\/p>\n<p>\/\/ handler definition<\/p>\n<p>slowDownDrawingHandler = <strong>new<\/strong> Handler() {<\/p>\n<p>\/** (non-Javadoc)*\/<\/p>\n<p>@Override<\/p>\n<p><strong>public<\/strong> <strong>void<\/strong> <strong>handleMessage<\/strong>(Message msg) {<\/p>\n<p><strong>super<\/strong>.handleMessage(msg);<\/p>\n<p>redraw();<\/p>\n<p>}<\/p>\n<p>};<\/p>\n<p>\/\/ Launching the Thread to update draw<\/p>\n<p>Thread background = <strong>new<\/strong> Thread(<strong>new<\/strong> Runnable() {<\/p>\n<p>\/**<\/p>\n<p>* The message exchanged between this thread and the handler<\/p>\n<p>*\/<\/p>\n<p>Message myMessage;<\/p>\n<p>\/\/ Overriden Run method<\/p>\n<p><strong>public<\/strong> <strong>void<\/strong> <strong>run<\/strong>() {<\/p>\n<p><strong>try<\/strong> {<\/p>\n<p><strong>while<\/strong> (<strong>true<\/strong>) {<\/p>\n<p>\/\/ Sleep<\/p>\n<p>Thread.<em>sleep<\/em>(100);<\/p>\n<p>\/\/ Do something<\/p>\n<p>myMessage = slowDownDrawingHandler.obtainMessage();<\/p>\n<p>\/\/ then send the message<\/p>\n<p>slowDownDrawingHandler.sendMessage(myMessage);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>} <strong>catch<\/strong> (Throwable t) {<\/p>\n<p>\/\/ just end the background thread<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>});<\/p>\n<p>\/\/ start the thread<\/p>\n<p>background.start();<\/p>\n<p>Using such a code, when your activity pauses or dies your thread is still alive and become an orphan thread. Nothing can stop it, neither inter-acts with it and it continues to run. This is a big fail.<\/p>\n<p>What is the right way to do it: You have to manage your thread state according to your activity state. In other words, when your activity pauses, you have to pauses your thread, when it resumes you have to resume your thread, when your activity dies, you thread must die\u2026.<\/p>\n<p>A simple way to do that is to use two atomic Booleans (synchronized boolean), isPausing and isStopping, change their value in the onResume, onPause, onCreate and onDestroy methods of your activity and use that boolean to pause or stop your thread.<\/p>\n<p>So the right code should look like that:<br \/>\n<strong>Good Code Example CAN BE USED<\/strong><\/p>\n<p>\/** * The handler \u00a0*\/<\/p>\n<p><strong>private<\/strong> <strong>final<\/strong> Handler slowDownDrawingHandler;<\/p>\n<p>\/** * An atomic boolean to manage the external thread&#8217;s destruction *\/<\/p>\n<p>AtomicBoolean isRunning = <strong>new<\/strong> AtomicBoolean(<strong>false<\/strong>);<\/p>\n<p>\/** * An atomic boolean to manage the external thread&#8217;s destruction *\/<\/p>\n<p>AtomicBoolean isPausing = <strong>new<\/strong> AtomicBoolean(<strong>false<\/strong>);<\/p>\n<p>\/** Called when the activity is first created. *\/<\/p>\n<p>@Override<\/p>\n<p><strong>public<\/strong> <strong>void<\/strong> <strong>onCreate<\/strong>(Bundle savedInstanceState) {<\/p>\n<p>\/\/ handler definition<\/p>\n<p>slowDownDrawingHandler = <strong>new<\/strong> Handler() {<\/p>\n<p>@Override<\/p>\n<p><strong>public<\/strong> <strong>void<\/strong> <strong>handleMessage<\/strong>(Message msg) {<\/p>\n<p><strong>super<\/strong>.handleMessage(msg);<\/p>\n<p>redraw();<\/p>\n<p>}<\/p>\n<p>};<\/p>\n<p>\/\/ Launching the Thread to update draw<\/p>\n<p>Thread background = <strong>new<\/strong> Thread(<strong>new<\/strong> Runnable() {<\/p>\n<p>\/**<\/p>\n<p>* The message exchanged between this thread and the handler<\/p>\n<p>*\/<\/p>\n<p>Message myMessage;<\/p>\n<p>\/\/ Overriden Run method<\/p>\n<p><strong>public<\/strong> <strong>void<\/strong> <strong>run<\/strong>() {<\/p>\n<p><strong>try<\/strong> {<\/p>\n<p><strong>while<\/strong> (isRunning.get()) {<\/p>\n<p><strong>if<\/strong>(isPausing.get()) {<\/p>\n<p>Thread.<em>sleep<\/em>(2000);<\/p>\n<p>}<strong>else<\/strong> {<\/p>\n<p>\/\/ Sleep<\/p>\n<p>Thread.<em>sleep<\/em>(100);<\/p>\n<p>\/\/ Do something<\/p>\n<p>myMessage = slowDownDrawingHandler.obtainMessage();<\/p>\n<p>\/\/ then send the message<\/p>\n<p>slowDownDrawingHandler.sendMessage(myMessage);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>} <strong>catch<\/strong> (Throwable t) {<\/p>\n<p>\/\/ just end the background thread<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>});<\/p>\n<p>\/\/ Initialize the threadSafe booleans<\/p>\n<p>isRunning.set(<strong>true<\/strong>);<\/p>\n<p>isPausing.set(<strong>false<\/strong>);<\/p>\n<p>background.start();<\/p>\n<p>}<\/p>\n<p>\/*(non-Javadoc) *\/<\/p>\n<p>@Override<\/p>\n<p><strong>protected<\/strong> <strong>void<\/strong> <strong>onPause<\/strong>() {<\/p>\n<p>\/\/and don&#8217;t forget to stop the thread<\/p>\n<p>isPausing.set(<strong>true<\/strong>);<\/p>\n<p><strong>super<\/strong>.onPause();<\/p>\n<p>}<\/p>\n<p>\/*(non-Javadoc) *\/<\/p>\n<p>@Override<\/p>\n<p><strong>protected<\/strong> <strong>void<\/strong> <strong>onResume<\/strong>() {<\/p>\n<p>\/\/and don&#8217;t forget to relaunch the thread<\/p>\n<p>isPausing.set(<strong>false<\/strong>);<\/p>\n<p><strong>super<\/strong>.onResume();<\/p>\n<p>}<\/p>\n<p>\/*(non-Javadoc) *\/<\/p>\n<p>@Override<\/p>\n<p><strong>protected<\/strong> <strong>void<\/strong> <strong>onDestroy<\/strong>() {<\/p>\n<p>\/\/and don&#8217;t forget to kill the thread<\/p>\n<p>isRunning.set(<strong>false<\/strong>);<\/p>\n<p><strong>super<\/strong>.onDestroy();<\/p>\n<p>}<br \/>\nSo, Thanks who?<br \/>\nThanks, Android2ee, the Android Programming Ebooks :o)<\/p>\n<p><a href=\"http:\/\/mathias-seguy.developpez.com\/\">Mathias S\u00e9guy<\/a><br \/>\nmathias.seguy.it@gmail.com<br \/>\nAuteur <a href=\"http:\/\/www.android2ee.com\/\">Android2EE<\/a><br \/>\nEbooks to learn Android Programming.<\/p>\n<p><a href=\"https:\/\/plus.google.com\/u\/0\/115788770291974884100\/about\">Retrouvez moi sur Google+<\/a><br \/>\n<a href=\"http:\/\/fr.twitter.com\/#%21\/android2ee\">Suivez moi sur Twitter<\/a><br \/>\n<a href=\"http:\/\/fr.linkedin.com\/pub\/mathias-seguy\/37\/a71\/a59\">Rejoignez mon r\u00e9seau LinkedIn<\/a> ou <a href=\"http:\/\/viadeo.com\/s\/uOYfm\">Viadeo<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>http:\/\/android2ee.blogspot.com\/2011\/11\/h &hellip; <a href=\"https:\/\/blog.zhenglei.net\/?p=255431\">\u7ee7\u7eed\u9605\u8bfb <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,18],"tags":[58,273,272],"class_list":["post-255431","post","type-post","status-publish","format-standard","hentry","category-linux","category-software-download","tag-android-2","tag-orphan","tag-thread"],"_links":{"self":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/255431","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=255431"}],"version-history":[{"count":1,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/255431\/revisions"}],"predecessor-version":[{"id":255432,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/255431\/revisions\/255432"}],"wp:attachment":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=255431"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=255431"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=255431"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}