crysis
crysis

Reputation: 1584

Android: What is wrong with my custom viewHolder?

I've used a custom ViewHolder class to instantiate views. I'm getting NullPointException on this code. Application runs fine if I comment out iconView.setImageResource and descriptionView.setText() lines in bindView function.

If two of them showing NullPointExcepttion, why not the rest?

ADAPTER CLASS:

 private final int VIEW_TYPE_TODAY = 0;
private final int VIEW_TYPE_FUTURE_DATE = 1;

public static class ViewHolder {
    public final ImageView iconView;
    public final TextView dateView;
    public final TextView descriptionView;
    public final TextView highTempView;
    public final TextView lowTempView;

    public ViewHolder(View view) {
        iconView = (ImageView) view.findViewById(R.id.list_item_icon);
        dateView = (TextView) view.findViewById(R.id.list_item_date_textview);
        descriptionView = (TextView) view.findViewById(R.id.list_item_forecast_textview);
        highTempView = (TextView) view.findViewById(R.id.list_item_high_textview);
        lowTempView = (TextView) view.findViewById(R.id.list_item_low_textview);
    }
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {

    int viewType = getItemViewType(cursor.getPosition());
    int locationid = -1;
    if(viewType == VIEW_TYPE_TODAY)
        locationid = R.layout.list_item_forecast_today;

    else if(viewType == VIEW_TYPE_FUTURE_DATE)
        locationid = R.layout.list_item_forecast;

    View view = LayoutInflater.from(context).inflate(locationid, parent, false);
    ViewHolder viewHolder = new ViewHolder(view);
    view.setTag(viewHolder);
    return view;
}

/*
    This is where we fill-in the views with the contents of the cursor.
 */
@Override
public void bindView(View view, Context context, Cursor cursor) {
    // our view is pretty simple here --- just a text view
    // we'll keep the UI functional with a simple (and slow!) binding.
    ViewHolder viewHolder = (ViewHolder) view.getTag();

    viewHolder.iconView.setImageResource(R.drawable.ic_launcher);

    long dateInMillis = cursor.getLong(ForecastFragment.COL_WEATHER_DATE);
    viewHolder.dateView.setText(Utility.getFriendlyDayString(context, dateInMillis));

    String description = cursor.getString(ForecastFragment.COL_WEATHER_DESC);
    viewHolder.descriptionView.setText(description);

    boolean isMetric = Utility.isMetric(context);
    double high = cursor.getDouble(ForecastFragment.COL_WEATHER_MAX_TEMP);
    viewHolder.highTempView.setText(Utility.formatTemperature(mContext, high, isMetric));

    double low = cursor.getDouble(ForecastFragment.COL_WEATHER_MIN_TEMP);
    viewHolder.lowTempView.setText(Utility.formatTemperature(mContext, low, isMetric));
}

XML list_item_forecast

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:orientation="horizontal"
    android:padding="16dp" >

    <ImageView
        android:id="@+id/list_item_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_weight="1"
        android:paddingLeft="16dp">
        <TextView
            android:id="@+id/list_item_date_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/list_item_forecast_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:id="@+id/list_item_high_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/list_item_low_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>


    </LinearLayout>

XML list_item_forecast_today

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:padding="16dp">

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical"
        android:gravity="center_horizontal">

        <TextView
            android:id="@+id/list_item_date_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/list_item_high_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/list_item_low_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>

Error is:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageResource(int)' on a null object reference
        at com.example.abhishek.sunshine.ForecastAdapter.bindView(ForecastAdapter.java:78)
        at android.support.v4.widget.CursorAdapter.getView(CursorAdapter.java:256)
        at android.widget.AbsListView.obtainView(AbsListView.java:2344)
        at android.widget.ListView.makeAndAddView(ListView.java:1864)
        at android.widget.ListView.fillDown(ListView.java:698)
        at android.widget.ListView.fillFromTop(ListView.java:759)
        at android.widget.ListView.layoutChildren(ListView.java:1659)
        at android.widget.AbsListView.onLayout(AbsListView.java:2148)
        at android.view.View.layout(View.java:15614)
        at android.view.ViewGroup.layout(ViewGroup.java:4968)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
        at android.view.View.layout(View.java:15614)
        at android.view.ViewGroup.layout(ViewGroup.java:4968)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
        at android.view.View.layout(View.java:15614)
        at android.view.ViewGroup.layout(ViewGroup.java:4968)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
        at android.view.View.layout(View.java:15614)
        at android.view.ViewGroup.layout(ViewGroup.java:4968)
        at android.support.v7.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:502)
        at android.view.View.layout(View.java:15614)
        at android.view.ViewGroup.layout(ViewGroup.java:4968)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
        at android.view.View.layout(View.java:15614)
        at android.view.ViewGroup.layout(ViewGroup.java:4968)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
        at android.view.View.layout(View.java:15614)
        at android.view.ViewGroup.layout(ViewGroup.java:4968)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
        at android.view.View.layout(View.java:15614)
        at android.view.ViewGroup.layout(ViewGroup.java:4968)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2102)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1859)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1077)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5884)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
        at android.view.Choreographer.doCallbacks(Choreographer.java:580)
        at android.view.Choreographer.doFrame(Choreographer.java:550)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5312)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)

Upvotes: 0

Views: 764

Answers (2)

Serikov
Serikov

Reputation: 1209

Your second layout (list_item_forecast) missing ImageView with list_item_icon id.
In ViewHolder constructor you set iconView with view with this id. It will be null in ViewHolder with second layout. Then in bindView method you access method of this null object - setDrawable.
You can add image view in second layout or check view type in bindView and use only relevant fields.
list_item_forecast_textview is missing in second layout too.

Upvotes: 1

Kristy Welsh
Kristy Welsh

Reputation: 8362

You are not instantiating the class ViewHolder(View view) with a view, so iconView is never initialized.

Try doing this instead:

ViewHolder viewHolder = new ViewHolder(view);

Upvotes: 0

Related Questions