Alright, so it's time to start creating
our app to download that RSS feed, and
display the data onto the screen. Now the
app itself is going to be pretty basic
but it will demonstrate some very
important concepts, including performing
operations on a separate thread, so that
the app doesn't appear to freeze while
it's performing a long-running task. Now
although it's getting rarer these days,
you may have actually seen android pop
up
ANR dialogues - ANR, by the way, stands
for application not responding, although
Google have changed the way that the
dialogues appear. In fact, I can make one
appear quite easily, by doing something
incredibly foolish with a few lines of
code. I'm actually going to add a loop to
the onCreate method. What I'll do
first, though, is I'm going to start my
emulator, so that it's ready. And we're
going to type in some code, while that's
actually starting. So again, we're
going to add this loop - we're going to
add this after the setContentView line,
and the loop's just going to say while
parentheses true, open the code block and
then we're going to put val x, lower case
val x equals 1, and that's actually it.
Now, in case it's not obvious, don't ever
do anything like this. What I've done is
created a loop that just goes round and
round forever, but doesn't do anything
other than give x the value of 1. So it's
a really pointless thing to do, but it
will prevent the onCreate method from
finishing, and will make the app freeze.
So when I go ahead now and run this on
my emulator -
give that a moment to compile.
Now we don't even get to see the usual
Hello World that Android Studio includes
in the default layout, and that's because
the display doesn't appear until after
onCreate terminates. So if I come over to
the app now. If I click on the back
button to stop the app, there's a short
pause, and what should happen is the
Android framework will now detect that
the app's frozen, and you can see that
that it's popped up on the screen now and,
at this point here, I can either wait or
close the app. And sometimes the app
really is doing something and you might
decide to wait, but I'm going to close
this one because it's never going to be
doing anything useful. So I'm gonna click
on Close app. So that was an extreme
example, but you can see that Android
doesn't like it when an app takes over
the device, and doesn't finish its job in
a reasonable amount of time. And there's
a very good reason for that,
which is that the user interface is
shared by all apps. So there's only one
screen on the device, so if one app is
taking it over and it refuses to
release it, then the device, effectively,
can't be used for anything else.
Now if you remember from the
discussion of the activity lifecycle,
when another activity is started, it
doesn't become visible until the on
Pause method of the current activity
finishes. Now this activity with the
infinite loop will never finish,
so if Android doesn't provide that
dialog as a way to kill the app, then the
device, effectively, couldn't do anything
else. Now remember that activities are
being interrupted all the time. One thing
that often interrupts what you're doing
on a phone, is an incoming phone call. If
your app prevents users from answering
the phone, well frankly, they're not going
to be very impressed. In fact, that won't
actually happened. Android is now
cleverer than that, and will let things
like an incoming phone call take over,
but the point still holds. If the user
wanted to make a phone call, they'd have to
close our rogue app first, and we've just
seen that it doesn't close until we tell
Android to kill it. So all of this is
really, really should hopefully
emphasize the point that it's important
that we think about what our apps are
actually doing, and we don't perform long
running tasks on the main thread. Doing
so will block the user interface. Now
you'll find the documentation referring
to the UI thread,
which means the thread that the user
interface is running on. So when we do
something like downloading data over the
Internet, we don't really have any
control over how long the process will
take. Sometimes the Internet can be very
slow, and sometimes even sites such as
Apple's can go down and become
unavailable. Now that would obviously
cause our download to take a long time,
and could cause our app to freeze while
it's waiting for that download to
complete. So the way to cope with this is
to run the download on a separate thread.
Now think of a thread as a way of
running code at the same time as other
code is also running. In fact, with modern
multiprocessor or multi-core devices,
that's exactly what does happen. The
thread will run on another processor or
core, while the user interface continues to
execute. Now writing multi-threaded
applications is notoriously difficult,
and even experienced programmers
struggle to get it right. But fortunately,
Android provides a class that takes care
of all of the complexity for us. So we
can use an AsyncTask to perform the
download on a separate thread, and then
get notified when the download is
finished. So the download will happen in
the background, and the user interface
throughout the UI thread, will receive
the results of the download. So the
download will happen asynchronously,
which just means in the background on a
separate thread, and our app can get on
with other things while that's going on.
Now we can even switch to another app
and do something else while an async
task is running. This app won't allow
that, but we'll see ways to make that
possible later in the course. So
basically, we tell the Android framework
to get on with the task, then forget
about it until that task finishes. So
that's the theory, at least. Unfortunately,
though, using an AsyncTask to
communicate with the UI thread in Kotlin,
isn't quite as easy as it sounds. Now I'm
going to go ahead and use one anyway, but
in subsequent videos, we're going to
delete all this code and do it a bit
differently. Now there are a couple of
reasons for doing this. One is that most
of the google examples are still written
in Java, and probably will be for a while
yet. So that means that you're going to
be seeing the the Java way of doing
things, and the Kotlin way's often
very different. So this example will show
just how different it can be. Now the
other reason is that Android Studio will
actually convert Java code to Kotlin for
us. In fact, that's how I produced his
first lot of code that we're going to
see. I had to do a bit of tweaking but,
ultimately, that did work. However, what
it produces is basically Java code,
written with a Kotlin syntax. Now you
will find Kotlin code that's been
produced in this way, and you may even
end up having to maintain some. But
hopefully, by the time you've worked
through these next few videos, you'll be
better positioned to spot code like that,
and more importantly, you won't write any
more yourself. Alright, so let's start.
First thing I'm going to do is delete
that rogue while loop that we don't
want. So I'm going to come over here and
delete those three lines. Now most of the
time, new classes go into their own
Kotlin file, but this class is going to
access properties of our MainActivity,
so therefore, I'm going to create it as
an inner class. So normally, I'd
right-click on the package and choose
New then Kotlin Class, and that would
create a new class. But here we don't
want to do that, because we're going to
create the class inside the Main
Activity class. So I'm going to call this
one
download data, and it's just the same as
any other Kotlin class, except that it
can only be used by MainActivity. So in
other words, it's not visible to any
other class in the program. So I come
down here and add this code. I'm going to
clean that space up and then below the
onCreate function, I'm going to type
private inner class DownloadData : I'm
gonna type AsyncTask. Press Enter there,
and I'm going to add the diamonds and then
put string - or add a diamond operator,
I should say - String comma Void comma
String. Then at the right of the diamond
operator I'm going to add parentheses.
Then add the left and right curly braces.
Now at the moment, we've got an error
there, but what I've done is, I've created
a new class that extends the AsyncTask
class.
Now extending an existing class, which is
also known as sub-classing, lets you take
advantage of all the processing in the
existing class. So here what we're doing,
is taking advantage of the asynchronous
processing that the Android framework
provides. And all we have to do is
provide the code for the task that we
want to perform, and then let Android
take care of all the multi-threading
complexity for us. Now we need to set up
three parameters when we create an Async
Task, so that Android knows what type
of task we're dealing with. Now here we're
saying that the information that we'll
provide to the task, will be of type
string. So we're going to pass in the URL,
in the RSS feed, and we're going to store
that as a string. This is that first
parameter here, first argument - string. Now
the second parameter's used if we want
to display a progress bar - that's this
one.
Now our download is quite small, so there
won't be time for a progress bar to be
displayed. Now if we were downloading
large amounts of data, that could perhaps
take a few minutes or more to download,
then it might be a good idea to give the
user some idea of how long it'll take,
and also how far through we were. But
as we're not going to do that, I'm
making the second type here void, to show
that we're not actually using that. Now
onto the third parameter - this is the
type of the result that we want to get
back. So all our XML will be a string, so
we're using string again for the third
parameter type. Now you can find out more
information on the AsyncTask class in
Google's documentation. Let's just
open it up briefly. I'm just going to
paste this over the top of our RSS feed.
Now at the moment, as I mentioned, a lot
of Google's examples, and including this
one, as at the time of recording this
video, is still in Java and not Kotlin,
unfortunately, and that's one reason why
Kotlin programmers need to have some
familiarity with the Java language. Now
we will look at how Android Studio can
make life a lot easier for us, so don't
think, by any means, that you need to be
an expert Java programmer to work
through this course. Alright, so that's
the three parameters that I've talked
about here, that we need to define when
we setup an AsyncTask,
so that Android knows what type of task
we're dealing with. The first parameter,
again, will be a string containing, or
holding, the address of the RSS feed.
We're not using the second parameter at
all, and the third will be the string
containing all the XML that we've
downloaded. Now Android Studio's
actually showing an error here,
and that's because if we're going to be
using an AsyncTask, then there are some
functions that we need to implement. Well,
actually, there's only one function that
we must implement, and that's the doin
Background function. We can hover
over there - you can see that it's telling
us that it's really looking for this
doInBackground. It's basically saying
that the class DownloaData is not
abstract and does not implement an
abstract base class member. But as it
turns out, we're also going to implement
another function, though. Because we want
to get data back when the task completes,
we need to implement the on post
execute function. Android will call that
function when the job's done. Without
that, there wouldn't be a way for us to
know that the task had finished, and
therefore we wouldn't get the result. Now
we can get Android Studio to create the
base stubs for the methods, by using ctrl
o to get a list of the methods that are
available to override or implement. You
do want to make sure that your cursor is
in the inner class for that to happen,
and once you do that, you can just do a
ctrl o, and that brings up a list of
potential functions that can be
overridden. And, of course, we saw that in
an earlier video when we overrode the
methods in the Activity Lifecycle. so as
you can see, there are a few methods
available, and if we're updating a
progress bar then we want to do that in
the on, we want to use rather, the on
ProgressUpdate function, and the on
PreExecute function would be used to set up
the progress bar, for example, but can
also be used with setting up anything
else that's needed for our task to run.
Now both of those methods are called on
the main UI thread, otherwise they
wouldn't be able to display anything. So
it's important not to do anything like
trying to start the download in onPre
Execute. Now the other method we want,
though, is onPostExecute, which also runs
on the main UI thread, once the
background process has completed. So,
therefore, we're going to choose both
doInBackground
and we're gonna choose
onPostExecute, which was already selected,
and then we're going to click on Ok. And
you can see that those two functions
have now been created, and the error
message has disappeared. Alright, so I'm
going to start the code to do the
downloading in the next video. But what
I'm going to do for now is just put some
logging into these functions, so that we
can see what's going on and get a feel
for how the AsyncTask works. So we're
going to need a log tag for each of our
classes. So I'm going to come up, firstly,
to our MainActivity, and the first line
after the definition for our Main
Activity, I'm going to type private val,
TAG in uppercase, equals double quotes
MainActivity, in double quotes. So we can
now use that tag when logging in Main
Activity's onCreate function, and we can go
ahead and do that. We can type log.d
parentheses and tag comma,
and we can just type onCreate called. Let's
do the same for the DownloadData inner
class. So I'm going to come down into the
first, or the first line after the definition,
and we're going to type private val TAG
equals DownloadData. Alright, so now that
I've added those tags, we'll finish the
video here. In the next video, we'll start
continuing on with this program, and
we're going to start, in that next video,
by looking at the warnings that Android
Studio are popping up. So I'll see you in
the next video.