Alright, so at the moment, we've got an
interface that's not terribly pretty, and the
options for formatting the information
are fairly limited when you're using the
basic ArrayAdapter class. But this
example does demonstrate how easy it is
to use the ListView and an Adapter
together. Now if we wanted more control
over exactly what happens in the
ListView, we then have to create our own
Adapter, and we'll actually do that in
the next video.
But what I want to do, though, is go
through and we're going to comment out
the toString method - the to
String method in the FeedEntry class -
just to show that the basic Array
Adapter is using the object's toString
method to display the class data. And
it's also going to show you what the
default toString method produces. So
we're going back to our class,
so we can go to ParseApplications.
And if you remember, it was actually in
MainActivity class FeedEntry, which we
had in our MainActivity. So we're gonna
comment out the function - the toString
function. We're just gonna literally just
select all of it, up to and including the
closing right curly brace. Comment that out,
and if we actually run the app again
now,
you can see that we're just getting
the full class name and this strange
hexadecimal number here, that's actually
changing for each object.
Well that number's the hash code of each
instance of the FeedEntry class. So it's
not very user friendly and we're not
seeing any of the actual data in the
objects. So that's why it was a good idea
to override the toString
function, so that we could see the actual
data rather than this default
representation of the objects. So I
mentioned earlier that we have to cater
for the Activity being destroyed while
our AsyncTask's still running. Now that's
quite easy. We can just cancel the task
in the Activity's onDestroy method. Now
we're going to have to move the declaration of
downloadData to make it available in
onDestroy, but let's go ahead and write
the onDestroy method first. So I'm going
to go back to our MainActivity, and we're
going to put this just below the
onCreate, before the companion object
line. And we'll override - we're looking for
onDestroy. So we're getting Android
Studio to write the onDestroy stub
for us - or create the stub for us. So
in terms of the calls, we're going to
leave the super.onDestroy in there,
and we're gonna add this one extra line.
So it's gonna be downloadData dot
cancel parentheses true. Now at the
moment, downloadData is local to the
onCreate method, so to get this to
work we need to declare it at the top of
the class instead. So I'm going to come
up to the top of the class and do just
that, and we're going to put that just
below the initial TAG here. So
val downloadData is equal to
DownloadData with capital Ds for both
words, in parentheses this comma space
xmlListView.
Now I'm getting this warning here, or
this error; public properly exposes its
private type DownloadData. Now all
properties in Kotlin are public by
default, so downloadData's public. But
as its type in our private class -
come down here and have a look. We've got
the type set for private here in on line 52 -
that's what's causing a problem.
So you can't expose an object whose type
is private, so we have to make download
Data private, which it really should be
anyway, even if Kotlin doesn't enforce
this or didn't enforce this. There's no
reason why anything
outside MainActivity should be using
our DownloadData object anyway. So we're
gonna go back up and change this - it
should be private val. So we'll add the
keyword private, to satisfy Kotlin there.
Alright, so there's no error, but at the
moment it won't work though. So why won't
this work? Have a think about what's
being passed to the DownloadData
constructor here, and when we can
reasonably expect things to exist. Pause
the video now, and then I'll explain why
the code won't work, when you come back.
Alright, so did you figure out why? Well,
what's wrong with that code? Well the
problem's caused by passing the reference
to our ListView, to the constructor. Now
none of our widgets will exist until
after the call to setContentView, in
the onCreate method, and we saw this, if
you recall, in the calculator app. The
solution is to use by lazy, so that the
initialisation isn't performed until the
first time we need to use our download
Data object. So let's go ahead and change
that. So it should be private val
downloaData by lazy, and we'll get rid
of the equal sign, so by lazy. Then we
put left and right curly braces,
and we put 'this' in the left and right
curly braces, like so. So by the time we
use downloadData, the layout's been
created and the widgets are available in
our code. So if you're not clear about
that, review the discussion that we had
about this in the last section, about
using by lazy. Alright, so that's it - the
Activity's destroyed while our Async
Task's running and the task will be
cancelled. Now the other thing we need to
do is, obviously, comment out our val
downloadData, and what I didn't do was, I
probably should have actually copied
this line 41, and actually copied it over
and sort of pasted it or moved it, I
should say, back up to the reference here
on line 34, because obviously we've got
the definition of downloadData in two
places now. So, obviously, that's another
reason why we would have got an error
when we're actually running this. But the
point is, that should not be in there, so I'm
going to actually remove that now - remove that
entire definition on line 41. That's in
the onCreate function, because obviously
now, we've got the definitions showing up
here on line 34 in our MainActivity
class. And because, again, we're using by
lazy, the values are only going to get
updated when they're first accessed. Alright,
so let's just run this again, to make
sure it works. Alright, you can see that that's
still working. What I'll do is, I'll also
make a change and put back the to
String again, just so we can see the
normal values again. Then run it
again. Okay, so that's working nicely. So
now if the Activity is destroyed while
our AsyncTask's running, the task will be
cancelled. Now by the way, the boolean
argument to the cancel function - I'm
talking about this on line 40, code on line
47 - that tells Android that it can
interrupt the task, and that's why we're
passing true there, to say if that is okay
to do that. Now that may seem like a
strange thing to have to specify when
cancelling a task. However, you may want
the task to complete anyway, depending on
well it's doing. What you don't want, and
what would cause a crash, is if you then
try to pass its results back to the
Activity that's being destroyed. So there
are situations where you'd want to pass
false to the cancel function. Alright,
so I'm gonna stop the video here, and in
the next one we're gonna start creating
our own adapter. And this gives us far
more control over what appears in the
ListView, and it's also a good way to
understand how adapters work. So I'll see
you in the next video.