Sie sind auf Seite 1von 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.
And CPU two.
Each of these CPUs can carry out the
instructions that make up
the applications running on your device.
Now, on CPU two,
I'm showing two processes running, p3 and
p4.
Now, one way to think about processes
is that they're self contained execution
environments.
They have resources such as memory, open
files,
network connections, and other things that
they manage and
keep separate from other processes on your
device.
And within one of these processes, P4, I'm
showing two running threads, T7 and T8.
Now each of these threads is a
sequentially
executing stream of instructions with its
own call stack.
But since they're within the same process,
they can each access shared
process resources, including heap memory
and static variables.
In Java, threads are represented by an
object of type thread in the Java.Lang
package.
Java threads implement the runnable
interface, which
means that they must have a public
method, called a run, that takes no
arguments, and that has no return value.
Now, for this course, I'm assuming that
you've already learned about
Java threads, and that you know how to use
them.
However, if you need a refresher please
take a
look at the concurrency tutorial at the
following URL.
[BLANK_AUDIO]
Now some of the thread methods that we'll
see in this lesson include the
start method for starting a thread, and
the sleep method for temporarily
suspending a thread.
Some object methods that you may need when
you're
using, when you're using threads include
the wait method,
which allows the current thread to give up
a
lock that it holds and to wait until
another thread
invokes a corresponding method such as
notify or notify all.
And when this happens, the waiting thread
can reacquire the lock
that it gave up when it called wait, and
can continue executing.
The notify method wakes up a single thread
that is waiting on this object.
Now to use a thread, you normally do the
following things.
First, you create the thread.
For example, by using the new thread
command.
Now, threads don't automatically start
when you create them.
To start the thread, you need to invoke
the thread's start method.
Doing this eventually leads to the
thread's run method being called, and
the thread continues executing until that
run method terminates.
This graphic helps to show this behavior.
First, a running application issues a new
command to create a new thread object.
When this call finishes, the application
continues.
And some time later, invokes the thread's
start method.
And this call returns back to the
application,
but also causes the code in the thread's
run method to run as well.
And as the program continues, there are
now two threads executing.
And of course, you can do this multiple
times,
creating and executing as many threads as
you want.
So, lets look at an application in which
threading would be helpful.
The first application that we'll discuss
in
this lesson is called Threading No
Threading.
And as you'll see in a second, the
application displays a simple user
interface with two buttons.
The first button is labeled LoadIcon.
When the user clicks on this button, the
application opens and
reads a file containing a bitmap.
And once that's done, it shows the just
loaded bitmap on the display.
The idea here is that this operation takes
a noticeable amount of time.
Now, in the code I use throughout this
lesson, I'm actually going to exaggerate
how long this takes, okay?
But don't
let that distract you, the point is still
the same.
Some operations take a relatively long
amount of time.
And you, as a developer, have to
understand and deal with that.
The second button is labeled OtherButton,
when the user clicks
on this button a toast message pops up
displaying some text.
And the idea here is that if you see the
text,
then you know that the button's working.
Now, if you can't click the button, or
you don't see the text, then something's
wrong.
In particular, the user should be able to
click either of
the buttons, at any time, and the system
should just work.
So, let's run a version of this
application that does not use any
threading.
Now what do you think is going to happen?
Will I be able to press both buttons
whenever I want?
Let's see.
Here, I'll start up the
ThreadingNoThreading application.
As you can see, there are, there are the
two buttons that we talked about.
I'll first press the Other Button, and as
you can see, I
can click on it and the promised message
appears on the display.
Now I'm going to do two things.
I will first press the Load Icon button,
which will start the time
consuming operation of reading in the
bitmap from a file and then displaying it.
And right after I press the Load Icon
button, I'm going to press the Other
Button again.
Here we go.
Now, I'll press the Load Icon button, and
now 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 trying
to press the Other Button, Android
was still loading the icon for back when I
pressed the Load Icon button.
And that first operation was preventing
the second operation from taking place.
Okay, so one seemingly obvious, but
ultimately incorrect solution to
this problem, would be to go to the
listener that's
attached to the Load Icon button and
simply create a
new thread that loads the bitmap and then
displays it.
So I've implemented that approach in an
application called Threadingsimple.
Lets take a look at that application and
talk about why it doesn't actually work.
[BLANK_AUDIO]
So, here's the code for the
Threadingsimple application.
Here's the button listener for the Load
Icon button.
It calls the LoadIcon method, which is
listed just below.
This code creates a new thread, which
takes awhile loading the bitmap
and then tries to set the bitmap on an
image view that's part of the layout.
So let's run this code.
Now, I'll start-up the
application.
And now I'll press the Load
Icon button.
And now, I'll press the Other Button.
Well first off, I pressed the Other Button
and saw that it responded.
So loading the icon doesn't appear to
block pressing the Other Button.
So that's good, we've made some progress.
However, you can see that we've got a
bigger problem now.
We've crashed the application.
If we investigate the log cat output, we
see that there's a message telling us that
only the original thread that created a
view hierarchy can touch its views.
So, Android simply won't allow threads to
start messing
around with views that were created by
other threads.
So that means while the new thread that we
created to load the
bitmap can do that work, it can't actually
take the last step and
add the resulting bitmap to the display.
So
which thread actually created this
application's view hierarchy?
Well, all Android applications have a main
thread, which is also called the UI
thread.
Application components that run in the
same process, which
they all do by default, use the same UI
thread.
In all those life cycle methods that we've
been talking about, OnCreate, OnStart,
etc, they're all handled in the UI thread.
And in addition, the UI toolkit itself is
not thread safe.
And what all this means is that if you
block the UI thread with some long running
operation, then you're going to prevent
your application from
responding to other things that the user
is doing.
In fact,
we saw that in the ThreadingNoThreading
application.
So, long-running operations need to be put
in background threads.
At the same time however, we can't access
the UI toolkit from a non-UI thread.
And that's what got us into trouble with
the ThreadingSimple application.
[BLANK_AUDIO]
So, we need to do work in a background
thread, but when that
work is done we need to do the UI updates,
back in the UI thread.
And Android, in fact, gives us a bunch of
ways to do just that.
In particular, Android provides several
methods that
are guaranteed to run on the UI thread.
Two of those methods
are the view class's post method, and the
activity class's runOnUiThread.
Both of these methods take a runnable
parameter.
This runnable would, for example, contain
the code
that updates the display in our recent
examples.
So, if we're using these methods, we would
load the bitmap in
a background thread and when that
operation completes, we would use one of
these methods to execute a runnable that
then sets the bitmap on the display.
Let's see that in action.
So, here's my device.
And
I'll start up the threading viewpost
application.
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 the
Other Button.
And I expect to see that the Other Button
operation is not blocked by the Load Icon
operation.
And, I expect to see that the
icon actually loads without crashing the
application.
So, here it goes.
Now, I'll press the Load Icon button, and
now 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 as
well.
So here's
my application, open in the IDE.
I'll open up the main
activity for this application, and I'll go
straight to the
LoadIcon method, which gets called when
the user presses the Load Icon button.
As before, this code creates a new thread
and then loads the
bitmap.
But after the bitmap loads, you see
that we now have a call to view.post,
passing in a runnable, whose code actually
calls the setImageBitmap method to set the
just loaded bitmap on that image view.
[BLANK_AUDIO]

Das könnte Ihnen auch gefallen