Getting Custom List Adapter to properly inflate multiple linear layouts

pat picture pat · Jul 16, 2012 · Viewed 12.7k times · Source

I'm a little new to android and am trying to figure out these custom list adapter. So I have an activity that extends BaseListActivity and a function like:

public void inflate(){

    ArrayList<String> words = new ArrayList<String>();
    orders.add("hello");
    orders.add("world");

    wordsList = (ListView) findViewById(R.id.list);

    WordsAdapter adapter = new WordsAdapter(this, R.layout.single_word_container_item,words);
    wordsList.setAdapter(adapter);

And then I implement my custom WordsAdapter as follows:

public class WordsAdapter extends ArrayAdapter<String>{
    public Context context;
    public ArrayList<String> _words;

    //not sure the purpose of 'a' here
    public WordsAdapter(Context context, int a, ArrayList<String> words) {
        super(context, a, words);
        _words = words;
        this.context = context;
    }


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

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = inflater.inflate(R.layout.single_word_container_item, null);
        TextView wordName = (TextView) findViewById(R.id.wordName);
        if(!_words.isEmpty()){
            wordName.setText(_word.remove(0));
        }

        return v;
    }

}

From what I can tell from the logs is that getView is never being called. 'single_word_container_item' is simply an xml file with a layout that I want to inflate multiple times. I'm not sure about the entire process - I figured you set an adapter on your listview and then in that adapter you take care of displaying what will actually show up each time, so what am I doing wrong here? Currently I'm getting a null pointer exception where I set my adapter but earlier it just would not show anything. The logs show that it is getting into the WordsAdapter constructor but then dying. Thanks in advance for any advice.

EDIT: So it appears to be something wrong with identifying the listview in my xml.

If you use:

ListView
android:id="@+id/android:list" OR android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="wrap_content" 
ListView

the error is a null pointer exception when you use it

but if you define it as:

ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" 
ListView

you get the error: 07-15 19:18:50.240: E/AndroidRuntime(29842): Caused by: java.lang.RuntimeException: Your content must have a ListView whose id attribute is 'android.R.id.list'

EDIT: So apparently you can't extend listactivity and call setcontentview(). Since I need a view on top of the listview I don't want to extend list activity but rather call setcontentview and just refer to the list by its id.

Now my error is:

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread.

I tried calling adapter.notifyDataSetChanged() after my setAdapter() but that didn't seem to work. Am I supposed to call it somewhere else?

Answer

azgolfer picture azgolfer · Jul 16, 2012

You have an error in your getView() method:

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

    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v;
    if (convertView == null) {
       v = inflater.inflate(R.layout.single_word_container_item, null); 
    } else {
       v = convertView;
    }
    TextView wordName = (TextView) v.findViewById(R.id.wordName);

    // questionable logic
    if(!_words.isEmpty()){
        wordName.setText(_word.remove(0));
    }

    return v;
}

findViewById() must be called on the row's view.

Also look at the questionable logic above, what are you trying to do? This won't work too well if you are removing the listview objects directly from the adapter.