Services Are Not Threads7:39 with Ben Deitch
In this video we’ll add a separate Thread to our Service and drive home the point that Services are not Threads!
We just got an ANR by trying to do our downloading in our service. 0:00 But didn't we just say that services are an application component 0:04 that can perform long running operations in the background? 0:08 What gives? 0:11 Well, by default, 0:13 everything in an app runs on the main thread, including our service. 0:15 So even if a service is performing long running operations in the background 0:19 by default it will be doing those long running operations on the main thread. 0:23 If we want our service to do work on a separate thread, 0:28 we need to create that separate thread ourselves. 0:31 Seems simple enough. 0:35 Now let's make our download service do the downloading on a separate thread. 0:37 Let's close the Android manifest and start with some planning. 0:42 On the left is the code from when we created our own thread and main activity. 0:47 We created, named, and started the thread in the on create method. 0:52 Then, in the on click method of our button for each song we obtained and 0:58 set a message and then sent that message using our handler. 1:03 Now we need to replicate this in our service. 1:09 Just like an activity, a service also has a life cycle and life cycle methods. 1:12 And one of these methods is the good or onCreate method. 1:18 So we'll create, name and start our thread, in the onCreate method. 1:23 And since we've now replaced this message part with starting our service, 1:29 we should now be obtaining and 1:34 sending messages to our handler over here in the onStartCommand method. 1:35 All right. 1:42 Let's start and download service and remove the download song method. 1:43 We'll now be using our download handler and 1:53 it still has its download song method from before. 1:55 Let's also remove the call to download the song. 2:00 Then let's override our services on create method. 2:05 Let's place our cursor above onStartCommand and 2:09 use control O to override the onCreate method. 2:13 And let's delete this call to super. 2:19 We don't need it. 2:21 Now we need to create, name and start our thread just like we did in our activity. 2:24 Let's start by creating a new download thread at the top of the on create method. 2:32 Download thread thread equals new download thread. 2:38 Then on the next line, let's set the name of our thread. 2:46 Thread.setName DownloadThread. 2:50 And lastly let's start our thread, thread.start. 2:56 Next up, we need to send a message to our thread 3:04 each time on start command is called. 3:08 Under where we declare a song, let's obtain a message, and 3:12 set it to a new message variable. 3:15 Message message equals message.obtain. 3:17 Then let's attach our song variable to our message, 3:24 message.obj equals song, 3:27 and send the message using our handler, which we currently don't have access to. 3:33 Let's quickly create a field for our download handler. 3:39 private download handler 3:42 mhandler, then let's give it a value at the bottom of on Create 3:48 mhandler equals thread but mhandler. 3:55 Lastly, back in on StartCommand, 4:01 let's send our message, mHandler.sendMessage(message);, 4:04 great work! 4:13 Now that we're doing our download and a separate thread, 4:15 again we shouldn't have any issues with the app being slow or 4:18 not responding, but let's test it out just to be sure. 4:23 Let's click the download button and 4:32 yikes the app crashed If we look through the log. 4:36 And filter by errors. 4:46 It looks like we're getting a null pointer exception because we're trying to invoke 4:50 the virtual method, send message on a null object reference. 4:55 And if we click on the link to jump to the error 5:05 it looks like that null object is our handler. 5:10 Just like last time this is because our main thread 5:15 is ahead of our download thread. 5:18 The main thread has already finished the onCreate method and 5:21 moved on to the onStartCommand method all 5:25 before our download thread has even created our download handler. 5:28 To fix this, 5:35 let's make our main thread wait until the handler exists before we assign it. 5:36 Up in the on create method above the assignment 5:43 to mHandler,let's type while thread.m 5:49 handler equals null and add our brackets. 5:54 We shouldn't have to worry about a null handler any more. 6:00 Using an empty while loop like this definitely isn't the best practice. 6:05 But it's the best we can do with what we've learned so far. 6:10 Now let's test the app again and hopefully everything will work. 6:14 Also make sure you have the Android device monitor open so 6:20 we can see what happens when we kill our app's process. 6:24 And if we click the download button, it seems to be working. 6:28 And if we wait ten seconds, We can see our downloads start coming in. 6:35 Nice. 6:45 Now let's switch to the Android device monitor and kill our apps process 6:46 and if we check the log and scroll up a little bit, 6:55 we can see a scheduling restart of crashed service and there's our service. 7:01 It looks like it'll restart in 47 seconds. 7:10 So let's wait for 47 seconds and see what happens. 7:17 And look at that, our process came back. 7:24 And check it out. 7:29 Our downloads are happening again. 7:31 What's going on here? 7:34 Let's find out in the next video. 7:37
You need to sign up for Treehouse in order to download course files.Sign up