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) Using Parcelable Data Updating the Daily Forecast UI

Crash on Daily Forecast list scroll

I'm recieveing a NullPointerException when my list attempts to scroll on the Daily Forecast activity. The exception points to the ImageView fore the forecast icon. My code is listed below.

NullPointerException:

java.lang.NullPointerException: Attempt to read from field 'android.widget.ImageView com.kevmhaube.stormy.adapters.DayAdapter$ViewHolder.iconImageView' on a null object reference
            at com.kevmhaube.stormy.adapters.DayAdapter.getView(DayAdapter.java:58)

DayAdapter:

public class DayAdapter extends BaseAdapter {

    private Context mContext;
    private Day[] mDays;
    private ViewHolder holder;

    public DayAdapter(Context context, Day[] days) {
        mContext = context;
        mDays = days;
    }

    //Some code removed for length

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.daily_list_item, null);
            holder = new ViewHolder();
            holder.iconImageView = (ImageView) convertView.findViewById(R.id.iconImageView);
            holder.tempLabel = (TextView) convertView.findViewById(R.id.tempLabel);
            holder.dayLabel = (TextView) convertView.findViewById(R.id.dayNameLabel);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Day day = mDays[position];
        if (day != null) {
            holder.iconImageView.setImageResource(day.getIconId()); //Line of code with NullPointer
            holder.tempLabel.setText(Double.toString(day.getTempMax()));
        }

        if (position == 0) {
            holder.dayLabel.setText("Today");
        } else {
            holder.dayLabel.setText(day.getDayOfTheWeek());
        }

        return convertView;
    }

    //ViewHolder inner class!
    private static class ViewHolder {
        ImageView iconImageView;
        TextView tempLabel;
        TextView dayLabel;
    }
}

2 Answers

You need to declare holder as a ViewHolder just after the opening of the getView function

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if(convertView == null) {
            convertView = LayoutInflater.from(mContxt).inflate(R.layout.daily_list_item, null);
            holder = new ViewHolder();
            holder.iconImageView = (ImageView) convertView.findViewById(R.id.icon_image_view);
            holder.temperatureLabel = (TextView) convertView.findViewById(R.id.temperature_label);
            holder.dayLabel = (TextView) convertView.findViewById(R.id.day_name_label);

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

        Day day = mDays[position];
        holder.iconImageView.setImageResource(day.getIconId());
        holder.temperatureLabel.setText(Double.toString(day.getTemperatureMax()));

        if(position == 0) {
            holder.dayLabel.setText("Today");
        } else {
            holder.dayLabel.setText(day.getDayOfWeek());
        }

        return convertView;
    }

This is the line you are missing: ViewHolder holder; You get a null pointer because the first time you user holder it has not been declared as an object.

I already have it decorated, just as a member variable instead (force of habit).

Can you double check that in your day.java file you have this function:

 public int getIconId() {
        return Forecast.getIconId(mIcon);
    }

It does indeed have that method. The problem doesn't lie withing loading the list. The list is created just fine with the propper 7 Day forecast...it's whenever I try to scroll the list, I believe it's trying to make a new list item out of nothing, and getting that NullPointer exception.

if I remember the video correctly, the line that replaces the view item when scrolled is this:

holder = (ViewHolder) convertView.getTag();

can you set a break point on the line that is causing the issue and find out which variable is giving the null pointer?

jason phillips -- The holder itself yields "null", and holder.iconImageView ... holder.tempLabel ... and holder.dayLabel all cause the NullPointerExceptions.

oh i think i found it:

if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.daily_list_item, null);
            holder = new ViewHolder();
            holder.iconImageView = (ImageView) convertView.findViewById(R.id.iconImageView);
            holder.tempLabel = (TextView) convertView.findViewById(R.id.tempLabel);
            holder.dayLabel = (TextView) convertView.findViewById(R.id.dayNameLabel);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

in this block before the else you need to add this:

convertView.setTag(holder);

it should look like this:

if(convertView == null) {
            convertView = LayoutInflater.from(mContxt).inflate(R.layout.daily_list_item, null);
            holder = new ViewHolder();
            holder.iconImageView = (ImageView) convertView.findViewById(R.id.icon_image_view);
            holder.temperatureLabel = (TextView) convertView.findViewById(R.id.temperature_label);
            holder.dayLabel = (TextView) convertView.findViewById(R.id.day_name_label);

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

SUCCESS! :) Add that solution as an answer so I can give you Best Answer!