(bright music)
(swooshing)
(keyboard clicking)
Alright, so I mentioned at the end
of the last video that we've got a much more
efficient implementation of of the get view method.
But we can improve it a lot further.
And what we're going to do is we're to
employ something called the view holder
pattern to do that.
Now looking at this get view code
you can see we're using find view by ID
to get a reference to each of the widgets
in the view
and we're doing that every time.
Now even when we're reusing a few
we still have to find the individual text widgets
in order to change their text.
Now find view by ID is a really costly operation.
It takes a while to go through the view,
searching for the correct widget.
Now it is necessary to do that a lot of the time
but here we're reusing views, aren't we?
Which means we're calling find view by ID
to find the widgets in a view
that we've already searched last time
that we used it.
Now the widgets haven't changed since last time
so it makes since to store those references somewhere
and use it to store references to the text view widgets
rather than searching for them every time.
So that's what the view holder pattern does.
And it's called the view holder pattern
because it uses a smaller class to hold the views
that we found the last time.
So we're going to create a class that
has a field for each of the widgets
that we need to find.
Now the only other thing that we need is
some way to store the instances of this class
and view objects have a tag field that
can be used for that purpose.
So I'm going to type in the code
and then explain what it's doing.
But first we want to create a class called view holder.
Now this can be called anything but
the usual name is view holder.
Now because it's such a small class,
I'm going to put it at the start of the file.
So I'm going to open up our project again,
go into feed adaptor, well it's actually there anyway,
but I can go to the top there
and we're going to put it above the feed adaptor
class definition,
so I'll put it above that.
So it's going to be class view holder,
and notice when I start typing there
that the icon for feed adaptor in the project pane,
so it's a cut and class icon CK basically, so.
Now, class, view holder,
parenthesis V colon view, parenthesis
and we'll go through
and we'll add our curly braces.
We're going to type val, TV name, colon,
text view equals v.FindViewByID,
R.ID.TVname
next one, val, TV artist, colon,
it's also text view as you'll note,
and that's equal to V.FindViewByID,
R.ID.TVartist
and the last one is val, TV summary, colon,
text view equals V.FindViewByID,
R.ID.TVsummary
The other thing I would do is I'm going
to leave two lines
so two big lines between the classes.
Now that's actually a Python convention
but I think it does help to separate them
so it's now my convention that I'm using
for Kotlin until someone publishes a Kotlin style guide.
Alright so the view holder class is very basic.
It just uses find view by ID to find the widgets
in the view V
and stores them in its fields.
Now I'm doing this slightly different
to examples you find out there
so let's say what Google has to say about
the view holder pattern.
I'm going to just open a browser.
So paste that in.
Now the current examples are in Java
but we can see that the view holder is just a
basic class holding their references to the
fields that we want to update.
Now the first paragraph explains the reasons for it.
Coding point of view by ID frequently can
slow down performance.
You can see that over here.
Now Google's example puts the code to find view by ID
in the get view method.
Whereas I've always put them in the view holder class.
Now in Java I don't think it made any
difference either way
but in Kotlin the situation's slightly different.
So looking at the Java code that calls
find view by ID for each of the widgets,
scroll down there,
they're all initialised to null in the view holder class.
So if you want to do it that was in Kotlin
you're going to have to use the nullable text views
taught for our text views.
Now the way I'm suggesting avoids that.
The properties are initialised at the time
they're created
and we can use the num null text view type.
Now we don't like nullable types in Kotlin
so I'm sticking with this way of doing it.
Alright so back to the code,
and I'm just going to close that for now
and we'll update that later 'cause I've shown
you how to do that in a previous video,
alright so I'm going to change the get view method
to use the view holder,
then go through how it all works.
So we're going to go down to the get view method.
We're going to start by deleting these three lines.
Well actually these three lines up here.
And we're deleting them
because we don't need them any more.
Well actually what I'll do is I'll just comment
them out for now.
But we don't need them any more with this approach
we're about to take.
So what we want to do is create a new view holder object
if we're having to create a new view.
So we've got this code here up above
if convert view equals null.
And we've got the log here get view called with
null convert view.
That's where we're creating a new view.
So what we're going to do is we can put
view equals inflate,
inflate.inflate that's still correct.
What we're going to do after that is
we're going to top view holder equals view holder
parenthesis view
and we're going to do view.tag equals view holder.
And we'll clear up that area in a minute.
Now otherwise if it'd been past the view to reuse
then we're going to retrieve the view holder
from this tag with the else.
So we've got the view equals convert view
which is still correct
but then we've got to do view holder equals
view.tag as view holder.
Okay, alright so we've got this error
and that's because we need to declare our view holder.
So let's actually do that.
That's going to be at the start of the method
under the val view.
So we're going to put val view holder colon view holder
and that clears up most of those errors.
So all that's left now is to put the text
into the view holder's properties instead of
using the variables that we've deleted.
So let's go ahead and modify those lines.
The code down lines 60 through 62.
Bearing in mind that 62 was commented out
when we were testing in the previous video
so we're going to un-comment that.
We're going to change this though
instead of TVname.text equals current app.name
we're going to use the view holder instead.
So we'll put view holder,
dot in front of that,
and do that for all three lines.
Alright so what have we basically done here now?
Well if convert view is null,
we're doing that test on line 40,
we inflate a new view as before.
And also what we're doing then is creating
a new view holder object
and storing it in the view's tag
using the set tag method.
Well essentially that's what we're doing anyway
with the view.tag equals view holder.
Now if we have been given back an
existing view by the list view
then we're retrieving view holder from its
tag using the get tag method.
And in this case we're just accessing
the property view.tag
as view holder we're assigning that or
replacing that into our view holder variable.
Now the tag is an object so
we've got to cast it to a view holder
but we know it will be a view holder
because we put it there.
Now the Android framework doesn't use that tag field
so we can be sure that whatever we store in it
won't be touched by Android.
That's this as view holder when we're
actually casting it.
And within retrieving the application record
from the list as before
and setting it's values to the widgets that are stored
in the view holder.
And obviously we're doing that on lines 58 through 60.
So find view by ID is now called when a new
view has to be inflated otherwise
the widgets have already been found
and references to them are stored in the view holder.
Now when I run this app,
which I'm going to do now,
you probably won't notice much in the way
of performance.
In other words, much important improvement
in the speed
and that's because the new emulators are
actually very fast once they're started up.
Yeah you may not notice any speed improvements
on a modern Android device with this app either.
But when you come to add animations in
list views though
that's when you start to see the smoothing
scrolling that this approach allows.
So the improvement in the smoothness
of the scrolling can be readily,
can be really evident on older devices as well.
You can see that we still got it working now
and we've added the summary again now.
And you can see that it's working quite nicely.
There's no perceivable delay there.
But again you'd be more noticeable on an
older Android device
or if you're starting to use animations
in the list view for animating various views.
Alright now let's have a look at the log cat.
And we'll click on log cat
to open that up
and we'll go back to our current again.
Now as I scroll,
we can see the convert views being used,
get view provided a convert view.
We get new views created to start with
until the display fills up
but after that we're reusing the old views
that the list view passes back to get view.
Alright so that's our improved adaptor.
It now uses much less memory
and works more efficiently than the first version.
Now when you're creating your own adaptors,
reuse the views that you're giving them back
and use the view holder pattern to improve
the responsiveness of your app.
Now although Google recommends the view holder pattern
it didn't enforce it's use with the list view.
And when we come back to look at the new
recycler view widget you'll see that the
view holder pattern is enforced with that.
Alright so I'm going to reformat this code.
I'll close down the log cat first.
And what I'm also going to do is change the,
I'll go back to main activity,
and I'm going to change the limit that was set
to 200 back to ten just in case that will
prevent 200 items from
accessed in the future.
Now if you want to learn more about list views
and adapters then the talks from Google I/O
are available on YouTube
and these are highly recommended as they're
technical talks presented by the people
who create the Android code.
Now each year since 2008 Google have run Google I/O
to present the new technologies that they've created.
And it's largely devoted to technical presentations
covering things like Android
and Chrome,
and it's a great way to learn about what Google
has planned for the future
as well as getting information on their current
technologies from the programmers who create them.
And there's actually a talk on list views
and adapters from the 2010 Google I/O.
I'm just going to give you a link there.
And this will be in the resources section.
A very useful video to check out
and have a look at.
And I won't actually start playing it now
but you can see that it's obviously a
popular video
and there's a lot of people who subscribe
to this channel.
So very much worthwhile watching this video
to understand a lot more about list views
and adapters.
Alright so in the next video
we're going to add a menu to the app
so that we can choose form a selection of
feeds rather than just displaying the same one.
See you in the next video.