Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
In this video we’ll add a separate Thread to our Service and drive home the point that Services are not Threads!
Related Links
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