2

I have found these 2 answers: https://stackoverflow.com/a/11787066/1489990 and https://stackoverflow.com/a/18868395/1489990 that I have been trying to follow to accomplish a listview with different layouts for each item. My array adapter looks like this:

public class MyArrayAdapter<T> extends ArrayAdapter<T> {
    LayoutInflater mInflater;
    int[] mLayoutResourceIds;

    public MyArrayAdapter(Context context, int[] textViewResourceId, List<T> objects) {
        super(context, textViewResourceId[0], objects);
        mInflater = (LayoutInflater)context.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
        mLayoutResourceIds = textViewResourceId;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        LayoutInflater inflater = null;
        int type = getItemViewType(position);
        // instead of if else you can use a case
        if (row  == null) {
            if (type == TYPE_ITEM1) {
                //infalte layout of type1
                row = inflater.inflate(R.id.item1, parent, false); //*****************
            }
            if (type == TYPE_ITEM2) {
                //infalte layout of type2
            }  else {
                //infalte layout of normaltype
            }
        }
        return super.getView(position, convertView, parent);
    }

    @Override
    public int getItemViewType(int position) {
        if (position== 0){
            type = TYPE_ITEM1;
        } else if  (position == 1){
            type = TYPE_ITEM2;
        }
        else
        {
            type= TYPE_ITEM3 ;
        }
        return type;    //To change body of overridden methods use File | Settings | File Templates.
    }

    @Override
    public int getViewTypeCount() {
        return 3;    //To change body of overridden methods use File | Settings | File Templates.
    }
}

and my onCreate:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String[] array = new String[] {"one", "two", "three", "four", "five", "six"};
    List<String> list = new ArrayList<String>();
    Collections.addAll(list, array);

    ListView listView = new ListView(this);
    listView.setAdapter(new MyArrayAdapter<String>(this, new int[] {android.R.layout.simple_list_item_1, android.R.layout.simple_list_item_single_choice}, list));
    setContentView(listView);
}

This issue is that in my array adapter the line:

row = inflater.inflate(R.id.item1, parent, false);

gives the error:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean)' on a null object reference

And I am a bit confused as to the structure for the xml layouts. Right now I have 1 xml for the listView and a seperate one for the first list layout, and I tried making it all in 1 xml layout but it still gave the null pointer exception. I need some guidance as to how to accomplish this. Thanks

Community
  • 1
  • 1
ez4nick
  • 9,756
  • 12
  • 37
  • 69

2 Answers2

2

You forget to correctly initialize your inflater. You set it explictly to null (LayoutInflater inflater = null;), so when calling inflater.inflate(R.id.item1, parent, false);, it throws the NPE.

May are you looking to use your mInflater variable ?

 row = mInflater.inflate(R.id.item1, parent, false);

But I'll get rid of this mInflater variable and do this in the getView method directly :

public class MyArrayAdapter<T> extends ArrayAdapter<T> {
    int[] mLayoutResourceIds;

    public MyArrayAdapter(Context context, int[] textViewResourceId, List<T> objects) {
        super(context, textViewResourceId[0], objects);
        mLayoutResourceIds = textViewResourceId;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        int type = getItemViewType(position);
        // instead of if else you can use a case
        if (row  == null) {
            LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            if (type == TYPE_ITEM1) {
                //infalte layout of type1
                row = inflater.inflate(R.id.item1, parent, false); //*****************
            }
            if (type == TYPE_ITEM2) {
                //infalte layout of type2
            }  else {
                //infalte layout of normaltype
            }
        }
        return super.getView(position, row, parent);
    }
    /**
     * Other stuff 
     */
}
Alexis C.
  • 91,686
  • 21
  • 171
  • 177
  • Thanks that was able to fix my first issue. Now that it is fixed I see the list view with one, two, three,... and I changed a line to include my layout 'listView.setAdapter(new MyArrayAdapter(this, new int[] {R.layout.item1, android.R.layout.simple_list_item_single_choice}, list));' but it gives me the error java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView – ez4nick Jan 04 '14 at 23:36
  • @ez4nick I suggest you to ask another question with your actual code and the error message. That will be simpler to solve the issue. – Alexis C. Jan 06 '14 at 13:42
0

What is the name of your layout file? is it item1.xml? if that is the case you need to refer to it as R.layout.item1

row = mInflater.inflate(R.layout.item1, parent, false);

You also created a reference to inflater in the constructor, but you then set it to null in the getView method. Use mInflator and remove the inflator = null line

Or Bar
  • 1,566
  • 11
  • 12