5 - 5 - Threads, AsyncTasks & Handlers - Part 1 (15-32)

7
Hi, I'm Adam Porter, and this is Programming Mobile Applications for Android Handheld Systems. Handheld systems, like all computing devices today, increasingly contain multiple computing cores. And one thing this means is that multiple programs, or execution threads, can be running on your device all at the same time. And that's a powerful thing, because it lets you do more work in a shorter amount of time. But it can also make your programs much more complex, leading to errors and performance problems if you're not careful. So in this lesson, we're going to talk about writing multi-threaded programs for Android. And we're also going to discuss some of the classes that Android provides to support this. In particular, in this lesson I'll start with a brief discussion of threading itself. Next, I'll talk about Android's user interface thread, the main thread in which Android applications perform most of their work. And I'll also discuss how this impacts the design of your application software. After that, I'll talk about the AsyncTask class, which helps to simplify threading in Android. And finally, I'll wrap up with a discussion of the handler class, another Android threading mechanism. So, I keep using the term thread, but what is a thread? Well, essentially, a thread is one of possibly many computations running at the same time within a operating system process. In terms of implementation, each thread has its own program counter and run time stack, but shares the heap and static memory areas with other threads running within an operating system process. Now this graphic depicts these concepts, and here I'm showing a hypothetical computing device. Now, this device has two CPUs. CPU 1.

Transcript of 5 - 5 - Threads, AsyncTasks & Handlers - Part 1 (15-32)

Page 1: 5 - 5 - Threads, AsyncTasks & Handlers - Part 1 (15-32)

Hi, I'm Adam Porter, and this isProgramming Mobile Applications forAndroid Handheld Systems.Handheld systems, like all computingdevicestoday, increasingly contain multiplecomputing cores.And one thing this means is that multipleprograms, or executionthreads, can be running on your device allat the same time.And that's a powerful thing, because itlets youdo more work in a shorter amount of time.But it can also make your programs muchmore complex, leading to errors andperformance problems if you're notcareful.So in this lesson, we're going totalk about writing multi-threaded programsfor Android.And we're also going to discuss some ofthe classes that Android provides tosupport this.In particular, in this lesson I'll startwith a brief discussion of threadingitself.Next,I'll talk about Android's user interfacethread, the mainthread in which Android applicationsperform most of their work.And I'll also discuss how this impacts thedesign of your application software.After that, I'll talk about the AsyncTaskclass, which helps to simplify threadingin Android.And finally, I'll wrap up with adiscussion of the handlerclass, another Android threadingmechanism.So, I keep using the term thread, but whatis a thread?Well, essentially, a thread is one ofpossibly many computationsrunning at the same time within aoperating system process.In terms of implementation, each threadhas its ownprogram counter and run time stack, butshares theheap and static memory areas with otherthreads running within an operating systemprocess.Now this graphic depicts these concepts,andhere I'm showing a hypothetical computingdevice.Now, this device has two CPUs.CPU 1.

Page 2: 5 - 5 - Threads, AsyncTasks & Handlers - Part 1 (15-32)

And CPU two.Each of these CPUs can carry out theinstructions that make upthe applications running on your device.Now, on CPU two,I'm showing two processes running, p3 andp4.Now, one way to think about processesis that they're self contained executionenvironments.They have resources such as memory, openfiles,network connections, and other things thatthey manage andkeep separate from other processes on yourdevice.And within one of these processes, P4, I'mshowing two running threads, T7 and T8.Now each of these threads is asequentiallyexecuting stream of instructions with itsown call stack.But since they're within the same process,they can each access sharedprocess resources, including heap memoryand static variables.In Java, threads are represented by anobject of type thread in the Java.Langpackage.Java threads implement the runnableinterface, whichmeans that they must have a publicmethod, called a run, that takes noarguments, and that has no return value.Now, for this course, I'm assuming thatyou've already learned aboutJava threads, and that you know how to usethem.However, if you need a refresher pleasetake alook at the concurrency tutorial at thefollowing URL.[BLANK_AUDIO]Now some of the thread methods that we'llsee in this lesson include thestart method for starting a thread, andthe sleep method for temporarilysuspending a thread.Some object methods that you may need whenyou'reusing, when you're using threads includethe wait method,which allows the current thread to give upalock that it holds and to wait untilanother threadinvokes a corresponding method such asnotify or notify all.And when this happens, the waiting threadcan reacquire the lock

Page 3: 5 - 5 - Threads, AsyncTasks & Handlers - Part 1 (15-32)

that it gave up when it called wait, andcan continue executing.The notify method wakes up a single threadthat is waiting on this object.Now to use a thread, you normally do thefollowing things.First, you create the thread.For example, by using the new threadcommand.Now, threads don't automatically startwhen you create them.To start the thread, you need to invokethe thread's start method.Doing this eventually leads to thethread's run method being called, andthe thread continues executing until thatrun method terminates.This graphic helps to show this behavior.First, a running application issues a newcommand to create a new thread object.When this call finishes, the applicationcontinues.And some time later, invokes the thread'sstart method.And this call returns back to theapplication,but also causes the code in the thread'srun method to run as well.And as the program continues, there arenow two threads executing.And of course, you can do this multipletimes,creating and executing as many threads asyou want.So, lets look at an application in whichthreading would be helpful.The first application that we'll discussinthis lesson is called Threading NoThreading.And as you'll see in a second, theapplication displays a simple userinterface with two buttons.The first button is labeled LoadIcon.When the user clicks on this button, theapplication opens andreads a file containing a bitmap.And once that's done, it shows the justloaded bitmap on the display.The idea here is that this operation takesa noticeable amount of time.Now, in the code I use throughout thislesson, I'm actually going to exaggeratehow long this takes, okay?But don'tlet that distract you, the point is stillthe same.Some operations take a relatively longamount of time.And you, as a developer, have to

Page 4: 5 - 5 - Threads, AsyncTasks & Handlers - Part 1 (15-32)

understand and deal with that.The second button is labeled OtherButton,when the user clickson this button a toast message pops updisplaying some text.And the idea here is that if you see thetext,then you know that the button's working.Now, if you can't click the button, oryou don't see the text, then something'swrong.In particular, the user should be able toclick either ofthe buttons, at any time, and the systemshould just work.So, let's run a version of thisapplication that does not use anythreading.Now what do you think is going to happen?Will I be able to press both buttonswhenever I want?Let's see.Here, I'll start up theThreadingNoThreading application.As you can see, there are, there are thetwo buttons that we talked about.I'll first press the Other Button, and asyou can see, Ican click on it and the promised messageappears on the display.Now I'm going to do two things.I will first press the Load Icon button,which will start the timeconsuming operation of reading in thebitmap from a file and then displaying it.And right after I press the Load Iconbutton, I'm going to press the OtherButton again.Here we go.Now, I'll press the Load Icon button, andnow I'll press the other button.Okay.So, so what's going on here?The Other Button seems to be stuck.Why is that?Well, the answer is that when I was tryingto press the Other Button, Androidwas still loading the icon for back when Ipressed the Load Icon button.And that first operation was preventingthe second operation from taking place.Okay, so one seemingly obvious, butultimately incorrect solution tothis problem, would be to go to thelistener that'sattached to the Load Icon button andsimply create anew thread that loads the bitmap and thendisplays it.So I've implemented that approach in an

Page 5: 5 - 5 - Threads, AsyncTasks & Handlers - Part 1 (15-32)

application called Threadingsimple.Lets take a look at that application andtalk about why it doesn't actually work.[BLANK_AUDIO]So, here's the code for theThreadingsimple application.Here's the button listener for the LoadIcon button.It calls the LoadIcon method, which islisted just below.This code creates a new thread, whichtakes awhile loading the bitmapand then tries to set the bitmap on animage view that's part of the layout.So let's run this code.Now, I'll start-up theapplication.And now I'll press the LoadIcon button.And now, I'll press the Other Button.Well first off, I pressed the Other Buttonand saw that it responded.So loading the icon doesn't appear toblock pressing the Other Button.So that's good, we've made some progress.However, you can see that we've got abigger problem now.We've crashed the application.If we investigate the log cat output, wesee that there's a message telling us thatonly the original thread that created aview hierarchy can touch its views.So, Android simply won't allow threads tostart messingaround with views that were created byother threads.So that means while the new thread that wecreated to load thebitmap can do that work, it can't actuallytake the last step andadd the resulting bitmap to the display.Sowhich thread actually created thisapplication's view hierarchy?Well, all Android applications have a mainthread, which is also called the UIthread.Application components that run in thesame process, whichthey all do by default, use the same UIthread.In all those life cycle methods that we'vebeen talking about, OnCreate, OnStart,etc, they're all handled in the UI thread.And in addition, the UI toolkit itself isnot thread safe.And what all this means is that if youblock the UI thread with some long runningoperation, then you're going to preventyour application from

Page 6: 5 - 5 - Threads, AsyncTasks & Handlers - Part 1 (15-32)

responding to other things that the useris doing.In fact,we saw that in the ThreadingNoThreadingapplication.So, long-running operations need to be putin background threads.At the same time however, we can't accessthe UI toolkit from a non-UI thread.And that's what got us into trouble withthe ThreadingSimple application.[BLANK_AUDIO]So, we need to do work in a backgroundthread, but when thatwork is done we need to do the UI updates,back in the UI thread.And Android, in fact, gives us a bunch ofways to do just that.In particular, Android provides severalmethods thatare guaranteed to run on the UI thread.Two of those methodsare the view class's post method, and theactivity class's runOnUiThread.Both of these methods take a runnableparameter.This runnable would, for example, containthe codethat updates the display in our recentexamples.So, if we're using these methods, we wouldload the bitmap ina background thread and when thatoperation completes, we would use one ofthese methods to execute a runnable thatthen sets the bitmap on the display.Let's see that in action.So, here's my device.AndI'll start up the threading viewpostapplication.And there are the two buttons.And again, I'm going to do two things now.I'll press the Load Icon button.And then right after that, I'll press theOther Button.And I expect to see that the Other Buttonoperation is not blocked by the Load Iconoperation.And, I expect to see that theicon actually loads without crashing theapplication.So, here it goes.Now, I'll press the Load Icon button, andnow I'll press the Other Button.There's the text from the Other Button,and finally, there's the bitmap.Let's take a look at the source code aswell.So here's

Page 7: 5 - 5 - Threads, AsyncTasks & Handlers - Part 1 (15-32)

my application, open in the IDE.I'll open up the mainactivity for this application, and I'll gostraight to theLoadIcon method, which gets called whenthe user presses the Load Icon button.As before, this code creates a new threadand then loads thebitmap.But after the bitmap loads, you seethat we now have a call to view.post,passing in a runnable, whose code actuallycalls the setImageBitmap method to set thejust loaded bitmap on that image view.[BLANK_AUDIO]