5 - 6 - Threads, AsyncTasks & Handlers - Part 2 (16-25)

download 5 - 6 - Threads, AsyncTasks & Handlers - Part 2 (16-25)

If you can't read please download the document

Transcript of 5 - 6 - Threads, AsyncTasks & Handlers - Part 2 (16-25)

[BLANK_AUDIO]HI, I'm Adam Porter and this isProgramming Mobile Applications forAndroid Handheld Systems.The next threading support class thatwe'll discuss is the AsyncTask class.This class provides a general frameworkformanaging tasks, that, as in our previousexamples,involve work that has to be shared betweena background thread and the UI thread.The general work flow that you follow whenyou're using an Async task,is that work is divided between abackground thread and the UI thread.The background thread performs the longrunningoperation, and can optionally report itsprogress.The UI Thread on the other hand, isresponsiblefor the initial setup of the long runningoperation.It's responsible for publishingintermediate progress information,should the background thread report any,and it's responsible forcompleting the operation after thebackground thread has done its work.AsyncTask is a generic class.It takes three type of parameters, Params,Progress, and Result.Params is the type of the parameters thatare input to the As-, to the AsyncTask.Progress is the type of any intermediateprogress reports, and result isthe type of the result that is computed bythe Async task.The workflow of an Async task goes asfollows, first, the onPreExecute methodis run in the UI thread before thedoInBackground method starts.OnPreExecute will usually set up the longrunning operation.After that, the doInBackground method doesthebulk of the operation in the backgroundthread.And this method takes a variable list ofinputparameters and it returns a result of typeresult.Now, while doInBackground is running, itcan optionally callthe publishProgress method, passing in avariable list of values whichpresumably provide some indication of thelong running operations progress.If the background thread makes calls topublishProgress, then some calls toonProgressUpdate would normallybe made in the UI thread, as long as thebackground thread is still running.And finally, onPostExecute will be calledin the UI threadwith the result, with the result returnedby the background thread as its parameter.Let's look at a version of ouricon loading application implemented withan Async task.[BLANK_AUDIO]Here I'll start up the thread Async taskapplication.It looks similar to the previous examples,but I've added a new UI element,a progress bar that represents how much ofthe bitmap loading has been done already.So, here I'll press the Load Icon button,and youcan see that a small progress bar hasappeared andit's slowly getting filled in.I'll now press the Other Button and we seethe familiar text pop up, and finally,there's the bitmap.Let's look at the source code for thisapplication.Here I will start up the threadAsycTaskapplication.Now I'll open the main activity file.And here I'm displaying the buttonlistener for the load icon button.This code creates a new instance of theload icon task.Andthen calls execute on it, passing in theicon's resource ID as a parameter.So let's look at the LoadIconTask class inmore detail.LoadIconTask is an Async task and its typeparametersare integer for params, integer forprogress, and bitmap for the result.The first method we'll look at isonPreExecute.This method is executed in the UI thread,and it'spurpose is to make a progress bar visibleon the display.The next method is doInBackground.This method receives an integer as aparameter.This integer is theresource ID for the bitmap that was passedin to the load icon task's execute method.DoInBbackground does the work of loadingthe bitmap.As it does this, it periodically callspublishProgress, passing in aninteger which represents the percentage ofthe loading that's been done so far.And again, this example's a bit contrivedin the hope of keeping things simple.The example might have been a bit morerealistic though,if we were downloading an image from theinternet, or if we were waiting for theresultfrom a database query, but hopefully thisstill givesyou a good flavor of how Async tasks work.The next method is onProgressUpdate.This method runs in the UI thread,receives the integer that was passed intopublishProgress, and then sets theprogress barto reflect the percentage of work done.And finally, the last method isonPostExecute.This method, again, runs in theUI thread, and it receives the just loadedbitmap as a parameter.It first makes the progress bar invisible,since that's no longerneeded, and then it sets the loaded bitmapon the image view.The last thing I want to talk about inthis lesson is the Handler class.Like the Async task, the Handler class isdesigned to support handing off workbetween two threads.The Handler class is more flexible,however, in that it will work forany two threads, not just for a backgroundthread and the UI thread.A Handler is associated with aspecific thread.One thread can hand off work to anotherthread by sending messagesor by posting Runnables to a Handlerthat's associated with that other thread.So first, let's discuss messages andrunnables, and thenwe'll get into the architecture of theHandler class itself.Now, you already know about runnables.You use these when the sender knowsexactly what work steps itwants performed, but it wants that workperformed on the Handler's thread.A message, on the other hand, is a classthat can contain datasuch as a message code, an arbitrary dataobject, and some integer values.And you usemessages when the sender thread wants toindicate an operation that should be donein another thread, but it leaves theimplementation of that operation to theHandler itself.So, now let's talk about how Handlers usethese messages and runnables.Each Android thread is associated with aMessageQueue and a Looper.The MessageQueue is a data structure.It holds messages and runnables.The Looper takes these messages andrunnables offof the MessageQueue and dispatches them asappropriate.Now this graphic depicts a thread a, thathas created a runnable.And that has used a Handler object to postthat runnable to the Handler's thread.When thread A does this, a runnable isplacedon the MessageQueue of the threadassociated with the Handler.Now something pretty similar happens withmessages.And this graphic depicts a thread B thathas created a message, and that isused a Handler's, a handler's sendMessagemethodto send that message to the Handler'sthread.When thread B does this, the message isplaced on the MessageQueue associated withthat Handler.Now, while all this is going on, theLooper object issitting there, just waiting for work toappear on the MessageQueue.And when that work does appear, the Looperreacts in one oftwo ways, depending on the kind of workthat has just arrived.Now, If that work is a message, the Looperwill handle the message bycalling the Handler's handleMessagemethod, and passing inthe message itself.If instead, that work is a runnable,then the Looper will handle it by simplycalling, that runnable's, run method.Now, here are some of the methods that youuse whenposting runnables to a Handler.We've already seen the post method, thereare a number of othermethods that allow you to schedule workfor execution at different times.For instance, you can use the postAtTimemethod to add arunnable to the MessageQueue, but to runit at a specific time.There is also a postDelayed method, andthat allows you to add a runnable to theMessageQueue, but torun it after a specified delay.If youwant to send messages, you first need tocreate the message.One way to do that is to use the Handler'sObtainMessage method, which gives youa message with the Handler already set.You can also use the messageclass's obtain method.And once you have the message, you'll wantto set the data for the message.There are a number of variations fordoing this so please check out thedocumentation.As with runnables, there are a number ofmethods that you can use to send themessage.There is the sendMessage method that wejust talked about.There's also a version that allows you toput the message atthe front of the MessageQueue to have itexecute as soon as possible.There's a sendMessageAtTime method toqueuethe message according to the specifiedtime.There's alsoa sendMessageDelayed method that queuesthe message at the current timeplus the specified delay.Let's look at the source codefor versions of our running example thatwere implemented using Handlers.Here's the ThreadingHandlerRunnableapplication.I'll now open up this application's mainactivity.And first, you see that this code iscreating a new Handler.This Handler will be created by the mainUI thread.So the runnables that this Handlerreceiveswill be executed in the UI thread.Now, here I'm showing you the buttonlistener for the load icon button.When the user presses the load iconbutton,this code creates and starts a new thread,whoserun method is defined by the runnable loadicon task.Let's look at that class.Now this run method begins by posting anewrunnable that when executed, will make theprogress bar visible.It continues by loading the bitmap.And while it's doing that,it periodically publishes its progress byposting anotherrunnable that calls setProgress on theprogress bar.It then posts a runnable that sets thenewly loaded bitmap on the display.And it finishes by posting a lastrunnable, then makes the progress barinvisible.Let's also look at a second version ofthis application that send messages,instead of posting runnables.Here's the ThreadingHandlerMessagesapplication.I'll now open up this application's mainactivity.And first, you see that this code iscreating a new Handler.And again, this Handler will be created bythe main UI thread.The work that this Handler performs willbe executed in the UI thread.As you can see,this Handler has a handleMessage method,inwhich it implements the various kinds ofwork.This method starts by checking the messagecode that's in the message.And then, it takes the appropriate actionfor that message code.For instance, if the code isset_progress_bar_visibility,then this code sets the visibility statusof the progressbar.If the code is instead progress_update,then this code sets the progress state onthe progress bar.If the code is set_bitmap, then the codesets the bitmap on the display.Now, let's go to the button listener forthe load icon button.Same as before, when the user presses theload icon button, thiscode creates and starts a new thread whoserun method isdefined by the runnable loadIcon task.And this runmethod begins by obtaining a message withthe code set toset_progress_bar_visibility, andwith an argument indicating that theprogress bar should be made visible.It then sends that message to the Handler,which will handle it, andmake the progress bar visible.It then continues by loading the bitmap.And while it's doing that, it periodicallypublishes progress by obtaining andsending a message with the codeprogress_update, and with an argument thatindicates the percent, the percentage ofwork done.This will result in the Handler callingsetProgress on the progress bar.It then obtains and sends a message to setthe newly loaded bitmap on the display.And finally, it sends a last message tomake the progress bar invisible.So that's all for this lesson on threads,Async tasks, and Handlers.Please join me next time when we'll talkabout alarms.Thank you.[BLANK_AUDIO]