Upgrading Our Thread8:06 with Ben Deitch
In this video we’ll refactor our Thread to use Handlers, Loopers, and Messages!
Now that we know how all of these pieces fit together. 0:00 It's time for us to get our hands dirty and 0:03 turn this boring self serve breed of truck into something a lot more robust. 0:05 Let's start by making a new class for our handler and 0:10 let's call it DownloadHandler And 0:14 let's make it extend the android.os.Handler class. 0:22 Then, back in our DownloadThread, 0:29 let's declare a public DownloadHandler field named M handler 0:32 mHandler. 0:45 Then, let's delete everything in the run method and 0:47 type Looper.prepare, 0:51 this creates a looper for a thread and also creates the message queue. 0:59 Next, let's initialize our handler by typing mHandler 1:05 equals new DownloadHandler. 1:10 By default, a handler is associated with the looper for the current thread. 1:16 Since we're in the run method of our DownloadThread, the current thread 1:20 will be our DownloadThread, instead of the main thread, perfect! 1:26 And once our handler is created, the last step is to call 1:31 Looper.loop to start looping over the message queue. 1:36 Back in main activity, let's take a look at our download buttons on click method. 1:43 When we click this button, we want to start downloading our playlist 1:50 one song at a time, like ordering a bunch of burritos at once. 1:54 So inside this method, we'll be sending messages, or runnables, to our handler for 2:00 processing. 2:04 Let's add a comment at the bottom of this method, to say. 2:05 Send Messages or Runnables 2:12 to Handler for processing. 2:17 But before we implement this, there's actually two problems we should fix. 2:22 The first problem is that we're still creating a new thread 2:27 each time we click the button. 2:31 Since we're trying to use just one thread with a message queue, this is no good. 2:33 The second, and much bigger issue, is that if we write this code, 2:39 it will cause a null pointer exception. 2:43 Here we are in the main thread, inside the onclick method. 2:47 We create a new thread, give it a name, start it and 2:51 then we start sending messages or runnables to the handler. 2:55 But look over here at our DownloadThread, 3:00 it's still working on getting set up and hasn't initialized the handler yet. 3:02 When we call thread start, our download threads run method and 3:08 will start executing almost immediately. 3:13 But as fast as that is, the main thread moves on to the next line even faster. 3:17 So when we try to communicate with our download threads handler, 3:24 it won't have been created yet and our app will crash with a null pointer exception. 3:28 We'll need to start our thread before we get to the OnClick method. 3:33 Let's cut out our thread code and paste it above in the on create method. 3:38 Awesome! Back in the on click method let's do some 3:49 more planning. 3:52 We could create a new runnable for each song we want to download. 3:55 But then we need to specify not only which song to download, but 3:59 also how to download it like bringing your own recipe to the burrito truck. 4:03 Wouldn't it be better if we could just give our handler a bunch of song titles 4:09 and we could trust it to handle them all by itself? 4:13 Yes, yes it would. 4:17 Let's start by changing our comment to no longer include runnables. 4:19 Then, let's add a for each loop to loop through the playlist. 4:25 For (String song : and Playlist.songs and 4:32 brackets, inside the loop, 4:37 let's create a new message variable named message. 4:40 And let set it equal to Message.obtain. 4:52 We could create a new message object, but 4:58 since messages are used all over the operating system, 5:01 Android keeps a pool of message objects available for us to use. 5:05 This way, Android doesn't need to keep creating and 5:10 deleting a bunch of message objects. 5:13 Once a message has been handled, it just goes back to the pool to be re-used. 5:16 Now that we've got our message, on the next line, 5:22 let's type message.obj = song;. 5:27 The OBJ property of a message lets us add any type of object we want to our message. 5:31 Since we want to tell our handler about a song to download, 5:39 we'll attach the song name to our message. 5:43 Lastly, we just need to send our message to our handler, so 5:47 it can be added to the message queue. 5:51 We can do this by typing thread.mHandler.sendMessage and 5:54 passing in our message. 6:03 And remember, that we should declare thread as final, so we can use it and 6:06 our onclick method. 6:10 This might have happened automatically, almost done. 6:12 The last thing we need to do, 6:16 is tell our handler what it should do, when it gets a message. 6:18 We can do this but over riding our handlers, handle message method. 6:23 Let's go to the download handler class, and 6:29 hit Ctrl+O to bring up the over ride dialog. 6:32 Then let's choose to override the handleMessage method. 6:35 And once we've done that, all we need to do is call our download 6:40 song method with the song name supplied by our message. 6:45 Let's cut the download song method out of our DownloadThread and 6:51 paste it into our DownloadHandler. 6:59 Then let's quickly update the tag constant Alt+Enter, 7:06 downloadhandler.class.get simple name and 7:11 instead of calling super.handlemessage. 7:15 Let's call downloadSong, and 7:19 pass in the song attached to our message, 7:23 msg.obj.toString, to turn it into a string. 7:29 Lastly, let's update the download song method to take in a song, String song. 7:37 And let's change the log message to include the song name. 7:45 Great work! 7:55 I know this stuff seems complicated, but you're doing a fantastic job. 7:56 And the next video, will test our app and learn about some potential improvements 8:01
You need to sign up for Treehouse in order to download course files.Sign up