Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android Android Lists and Adapters (2015) Custom ListViews getView() and the ViewHolder Pattern

Kevin Faust
Kevin Faust
15,353 Points

Creating objects that are static classes

Hey everyone,

Im a bit confused on what we did here:

private static class ViewHolder {
        ImageView iconImageView;
        TextView temperatureLabel;
        TextView dayLabel;
    }

We created a static class here but then look at this line: holder = new ViewHolder(); :

if (convertView == null) {
            //brand new
            convertView= LayoutInflater.from(mContext).inflate(R.layout.daily_list_item,null);

            holder = new ViewHolder();
            holder.iconImageView = (ImageView) convertView.findViewById(R.id.iconImageView);
            holder.temperatureLabel = (TextView) convertView.findViewById(R.id.temperatureLabel);
            holder.dayLabel = (TextView) convertView.findViewById(R.id.dayNameLabel);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

I thought the whole point of making something static was that so we dont have to create objects and can just access it's properties directly. Ben said that we had to use static but I'm not sure why.

Thank you

3 Answers

Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Hey Kevin, I haven't done this android course, but my understanding from java is this:

You can declare an inner nested class as static if you want it to have access to static variables in the outer class(the class that the static class is referred to)

You are correct that we use static in the event that we really only want one object and don't want to continually instantiate the object. However I would assume when designing this class whoever designed it that instantiating a view holder variable and constantly overwriting it (since it is static it would be overwritten with the properties of the next one upon creation).

I would have to assume that there's some static variables in the outer class that Ben by a design choice wanted this private class to be able to access alone.

Here's bit more information if you're interested.

Thanks! Let me know if this doesn't help or if there's something I can further explain.

Kevin Faust
Kevin Faust
15,353 Points

Hey Rob,

This is the the main code which im struggling with:

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder holder;

        if (view == null) {
            //brand new
            view = LayoutInflater.from(mContext).inflate(R.layout.daily_list_item,null);

            holder = new ViewHolder();
            holder.iconImageView = (ImageView) view.findViewById(R.id.iconImageView);
            holder.temperatureLabel = (TextView) view.findViewById(R.id.temperatureLabel);
            holder.dayLabel = (TextView) view.findViewById(R.id.dayNameLabel);

            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }

        Day day = mDays[i];

        holder.iconImageView.setImageResource(day.getIconId());
        holder.temperatureLabel.setText(day.getTemperatureMax() + "");
        holder.dayLabel.setText(day.getDayOfTheWeek());

        return view;
    }

    private static class ViewHolder {
        ImageView iconImageView;
        TextView temperatureLabel;
        TextView dayLabel;
    }

I still dont understand why we are using static. If we're just going to constantly override the ViewHolder variable, why couldn't have just done this.

            ViewHolder.iconImageView = (ImageView) view.findViewById(R.id.iconImageView);
            ViewHolder.temperatureLabel = (TextView) view.findViewById(R.id.temperatureLabel);
            ViewHolder.dayLabel = (TextView) view.findViewById(R.id.dayNameLabel);

I'm really trying to picture what we're doing in my head but this custom adapter stuff is really quite difficult.

Not sure how much android you know, but I was also wondering if you knew what these lines of code do:

view.setTag(holder);

and

holder = (ViewHolder) view.getTag();

Thanks,

Kevin

Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Hey Kevin, keep in mind we're only declaring a view object if it's null, so though it's possible that you'll declare it frequently more often than not as long as one is created you'll probably just use the one created with those objects made, again Ben probably had his reasons for making this a static inner class.

It may not make sense to us without seeing much of the backend, but remember Java is always running Garbage Collection, normally inner nested classes that are not declared static just expire once the outer class runs out. And non static inner classes expires as soon as the main class object does. And actually, if you don't have the outer class instantiated you can't create the inner inner class unless it's static.

Essentially the vibe I get from the code is that Ben wanted to instead of making a normal public class and setting the variables in the constructor in normal like how we'd normally see he chose to make it a private inner class so that it makes more sense to the users of the code (Treehouse Students) Exactly what is happening. Also, it could very possibly be that the view was taking up a lot of resources, so he decieded to move it a static inner class to save on some of that.

I don't know much about views, but from what I do know they are a convenience item that can hold data and information in a single variable elsewhere in the code instead of having to call the same method over and over again.

You see where they are setting up the items on the view and setting the ID, the image, temperature label and day label?

We are saving all that information, and saving it in the tag of this item and calling all those variables at once by just referencing tag.

Think of it like bag that we can carry our 3 items in, instead of having to carry each item in 3 hands.

The use of getters and setters makes me think that they want this code to be private and not directly modifiable, except by those methods.

Thanks, hope this helps.

Im thinking that you are spot on with making the class static due to it taking up a lot of resources. Like he said if it were to load 1000 objects that all needed to populate 1000 list view items then we would also have 1000 ViewHolder objects, instead of just the single ViewHolder object used 1000 times to contain redundant information he instead used a static class that would hold the information once. Being able to instantiate a static class is new to me but I'm assuming it has to do with it being an inner class for this adapter. The only time that if(convertView == null) will even come back as true is only when this adapter is instantiated since we will be using the tag attribute to populate the recycled views.

Rifqi Fahmi
Rifqi Fahmi
23,164 Points

I think ben instantiate the holder = new ViewHolder() so that it can be referenced in the setTag() method as argument cause I think its impossible to reference the ViewHolder class as the argument for the setTag()

Also why it set as static ? I think because we don't have to make the setter or getter method in that class to make changes of the member variable.