now that we've seen how to use a view
model and live data in a very simple app
it's time to look at something a bit
more complex when we finished the top to
him downloader app it still had one
floor we tried to avoid unnecessary yard
downloads as much as possible but the
app still downloaded the data again
after a configuration change such as
rotating the device at the time I
suggested that you could use a loader to
prevent this and said that would be
covering loaders later in the course
however in June 2018 Google deprecated
the loader classes so we're now going to
be using the view model plus instead
we've seen that a view model survives a
configuration change which means it
shouldn't have to download the data
again when the device is rotated so in
this video we'll start the process of
changing the top 10 downloader to use a
view model and solve this problem so
start with the top 10 downloaded project
open and you can see that I've got that
open on screen you can download that so
from the final video in section 7 where
we created the top 10 download our app
in this course if you need to so first
thing I'm looking at main activity you
can see it's got quite a bit of code
that's concerned with the UI as we
scroll down and check out so it needs to
keep track of the feed limit that the
user selected in order to make the menu
correctly reflect their choice now
because the feed limit is used to
construct the URL it makes sense to
leave responsibility for restoring feed
URL with main activity as well you may
decide to do things differently but I
like the fact that the view model isn't
going to know how to construct the gyro
it'll be given a fully form link to the
RSS feed and doesn't have to worry about
formatting it with different feed limits
so this separation of responsibilities
makes it easier to make changes to your
app without breaking things you could
use a different feed for example and the
view model would still work well so
moving down a bit further
most of the conveyor code in here is
concerned as I mentioned with the gyro
but looking down here we've got this
function that download gyro well that
shouldn't be in here because that's not
a UI function and also scorned a little
bit further we've looked towards the
bottom of the class
we've got this companion object and
that's the downloaded companion object
we shouldn't have that in this class
either well that's a good place to start
I think this download our companion
object so what I'm going to do is create
a new Copland file class let's go ahead
and do that it's a new Kotlin file class
we'll call this one download data now
because we're going to be cutting all
the code we've got all the code we need
I won't bother selecting class from the
drop-down so next we want to go back to
main activity we're going to cut all the
code out from the companion object from
the Declaration right through down to
the closing right tab curly brace
leaving just the companion line there
and I'm going to take the opportunity to
delete that as well cuz we won't be
needing that anymore I'm going to paste
that in the download data class that we
just created and that's when I got to
paste it we've got a lump of imports
that I've actually popped up now in this
case we don't want to import Android
widgets on this view so I'm gonna
unselect that one from the list and
obviously that's a UI related thing
which is why we're not including it okay
okay we've got that you know paste it in
to our downloaded data class this is a
basic async class and we you shouldn't
have to make too many changes to it what
I'll do you I'll start off by doing is
pasting or moving the tag to the top
level and make it a costs let's go ahead
and do that and that should be Const now
also we won't need a context for the
definition here or reference to the
ListView
in fact this class shouldn't have any
knowledge about the UI it's just going
to download and parse the data now it
will need to know what created it to
call it back when the data is available
and it shouldn't be marked private so
I'm going to delete that out for now
change the definition so it's no longer
private then within the parentheses
we're going to be using an interface
method to call back on and we'll write
that after the declaration but let's in
print parentheses add private val call
back :
I'll call it downloader call back
leaving everything else s is callback
will be the object that created the
download data instance
and we'll implement a function that we
can call so we'll get to the interface
shortly but what we can do now is remove
the two var declarations up here because
we're going to replace those in our
interface with our interface we're also
going to delete the init block there as
well all right so I'll go ahead now and
add our interface so interface and it's
download a callback then add a left or
right curly brace there's going to be
fun we can add a function fun it's going
to be on data available parentheses data
: and we're going to find this a list of
feed entry objects and lists and then a
diamond and there's going to be feed
entry alright so that's how it defines
so we've now got errors in the on post
execute function when we try to refer to
things like the adapter in the list view
again this class isn't concerned about
the UI it's just you know it just
downloads and passes the data and sends
the result back so what I'm going to do
is replace the code with a call to the
calling classes on data available
section let's go ahead and clean that up
a bit so I'm going to delete this super
and I believe the other tag entry that
we had there what we're also going to do
is only pass the data if result isn't an
empty string so on the line after the
VAR pars applications we'll do a test
for that
if parentheses result is not empty so
dot is not empty closing your
parentheses at a code block then and
only then when we do a pause and stop
pars result I could have just copied
that line there so I'm going to delete
that now again we're not concerned with
the UI so we're going to delete these
two lines here we don't want to want to
be updating the user interface here
instead what we're going to do is just
add that callback as I mentioned so
callback dot on data available we're
going to parse applications or paths
sparse applications dot applications
looking further down there the doing
background function is fine but that's
been making quite a significant change
to the app structure what I'm going to
do is rename all the logging there it is
useful to check that the function has
been called
I'll just move that back and at this
point we're done with the modifications
for this class but one thing I do want
to show you and what we need to change
is when we initially talked about and
set up this download XML function or
showing you how simple it was to do that
I did leave out the error handling we
had enough to concentrate on at the time
but now is a good opportunity to add
that back again so let's go ahead and do
that this is the download XML function
so I'm gonna start here by adding things
to a try block here so it's gonna be try
left curly brace and I'm gonna indent
the return there they'll have a closing
right curly brace then we need to catch
some exceptions so we'll start with a
catched ecole and we'll start with
malformed at URL exception so if you get
that we're gonna do a log d parentheses
tag comma download XML colon invalid
euro and closing double quote +
e.message so that's our first one next
what I'm going to do is annoy exception
so catch e : hi our exception same do
there with the log log D you could do
and logged on either but for debug
purposes I'm going to leave the log D in
there because that'll become useful a
few videos time so log D parenthesis tag
comma and download XML again just home
IO exception reading data is it getting
the error message then we'll let our
plus e dot message on the end again so
you get more details about what the
exception was I need to change that
reference to a lock I see there and the
third exception we want to catch is a
security exception e : security
exception log D parentheses ter comma
there's gonna be download XML : security
exception and we'll ask the question
needs permission question mark then
double quote + e dot message and what
you could do there as you can do an e
dot print stack trace if you wanted to
and done uppercase e there again
eat up print stack trace but I'll
actually comment it out for
now then one other thing we need to do
here though because we haven't closed
that in the Tri we need to return an
empty string in fact if there was an
exception so down here we little
returned an empty string and we just
make a quick note about that turn an
empty string if there was an exception
now what I would like to do is tidy up
these nullable parameters in the two
functions if we end up passing a null
string for the URL that's an error in
our code so I'd rather the app pressures
quickly so that we can detect the
problem in testing so for the doing
background I'm going to try to remove
the safe call operator there and also do
the same for our download XML function
download XML is our function so we're
obviously free to modify that one all we
want that doing background function you
may remember what's generated for us in
Android studio used a nullable type but
our async task if you come up and have a
look at that again that we've defined on
line 15 doesn't use nullable types so if
you're passing multiple values in an
array then it may well be wise to leave
the virag parameter as an array of a
nullable objects and perform an old test
inside doing background I'm not
suggesting that you always remove that
question mark but it is safe to do so
here all right so that's our download
data class finished in the next video
we'll swing over and start working on
our view model so I'll see you in the
next video