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

How to populate a Custom List Adapter with more than 2 values ?

In Android course we were taught how to do a Custom List View using ArrayList, but what if I want to put more than 2 values per row in a List View with a Custom Adapter?

What I decided to do was use a Object to populate my List my without success.

This is what I have till now:

Scorecard Activity:

<p>ObjectItem[] holeData = new ObjectItem[20];

for (int i = 1; i <= hole_counter; i++) {
            // Getting values from Shared Prefs
            strokeArray[i] = mySharedData.getInt("hole_" + i + "_stroke", 0);
            parArray[i] = mySharedData.getInt("hole_" + i + "_par", 0);
            // Populating Objects Array
            holeData[i] = new ObjectItem(i, strokeArray[i], parArray[i]);
        }

HoleListAdapter adapter = new HoleListAdapter(getListView().getContext(), holeData);
setListAdapter(adapter);

/** Object Items Class */
public class ObjectItem {
    public int hole;
    public int strokes;
    public int par;

    // constructor
    public ObjectItem(int hole, int strokes, int par) {
        this.hole = hole;
        this.strokes = strokes;
        this.par = par;
    }
}</p>

This is my custom adapter: HoleListAdapter

<p>public class HoleListAdapter extends ArrayAdapter<Scorecard.ObjectItem> {

protected Context mContext;
Scorecard.ObjectItem mHoleData[] = null;

public HoleListAdapter(Context context, Scorecard.ObjectItem[] holeData) {
    super(context, R.layout.scorecard_list_item, holeData);

    mContext = context;
    mHoleData = holeData;
}

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

    ViewHolder holder;

    if (convertView == null)
    {
        convertView = LayoutInflater.from(mContext).inflate(R.layout.scorecard_list_item, null);

        holder = new ViewHolder();
        holder.iconImageView = (ImageView) convertView.findViewById(R.id.pin_icon);
        holder.holeTextView = (TextView) convertView.findViewById(R.id.hole_number_title);
        holder.strokeTextView = (TextView) convertView.findViewById(R.id.stroke_number_title);
        holder.parTextView = (TextView) convertView.findViewById(R.id.par_number_title);

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

    Scorecard.ObjectItem objectItem = mHoleData[position];

    // HAVING ERROS ON THESE LINES BELOW
    holder.iconImageView.setImageResource(R.drawable.ic_pin);
    holder.holeTextView.setText(objectItem.hole);
    holder.strokeTextView.setText(objectItem.strokes);
    holder.parTextView.setText(objectItem.par);

    return convertView;
    }
    public static class ViewHolder {
    ImageView iconImageView;
    TextView holeTextView;
    TextView strokeTextView;
    TextView parTextView;
    }
}</p>

What is wrong ? Is there a best way to do what I want ?

This is my stack trace:

04-10 22:24:55.887  12660-12660/com.example.app E/AndroidRuntime? FATAL EXCEPTION: main
Process: com.example.app, PID: 12660
java.lang.NullPointerException
// The line below is the Error's Place that I mentioned in the HoleListAdapter Code
at com.gca.plusgolf.HoleListAdapter.getView(HoleListAdapter.java:54)

And the value that I have for mHoleData = [Lcom.example.app.Scorecard$ObjectItem;@433de628

Appreciate the help. tks.

3 Answers

Ben Jakuben
STAFF
Ben Jakuben
Treehouse Teacher

Everything looks okay...if you insert a breakpoint on the setImageResource line, what do you have in your objectItem and holder variables?

Ben, I've just debugged and my setImageResource and holder seems to be ok.

However the problem seems to be one line below with the objectItem that is null.

here is the trace:

objectItem = null 
objectItem.strokes = java.lang.NullPointerException 
objectItem.hole = java.lang.NullPointerException 
objectItem.par = java.lang.NullPointerException

What should I do ?

OK, I've just changed the line in (HoleListAdapter) from

Scorecard.ObjectItem objectItem = mHoleData[position];

to

Scorecard.ObjectItem objectItem = mHoleData[position + 1];

Because my for loop starts with 1 as you can see in Scorecard Activity.

When I debug now I have the values for objectItem, objectItem.strokes, objectItem.par, objectItem.hole instead of java.lang.NullPointerException but the app still breaking in the same line as my log prints. Maybe because the + 1 doesn't work for the second item ?

This is my stack trace now:

Process: com.example.app, PID: 17808
android.content.res.Resources$NotFoundException: String resource ID #0x1
Ben Jakuben
Ben Jakuben
Treehouse Teacher

Ah! Your loop should start at zero. The arrays you work with in that for loop, strokeArray, parArray, and holeData all start with index 0. Remember that arrays in Java use 0 to reference the first item in the array.

By setting i to 1, the first items are never getting set (and are thus null). That's why objectItem becomes null, which is where the error is manifesting.

Is hole_counter supposed to be 18? If so, then you probably want to use that same variable to initialize your arrays instead of 20, like this:

ObjectItem[] holeData = new ObjectItem[hole_counter];

Oh Ben, thanks! I redesigned everything but I still having the same error. BUT.... checking thoroughly I think that my problem is not in getting the data in objectItem but yes in targeting the TextViews... This is an image of my Debugger:

Debugger Img