views:

50

answers:

1

I have a ListView that I'm binding to an adapter. The adapter is a protected member of my main class. I have a listener thread that receives data and updates the source list for my adapter. When I call the adapter's notifyDataSetChanged() method, an exception is thrown:

Runtime Exception: PhoneLayoutInflater(LayoutInflater).inflate(int, ViewGroup, boolean) line: 322

I've read that the notifyDataSetChanged() method has to be called on the UI thread, and I'm doing that. In fact, just to be sure, I even update the ListView's data source on the UI thread. All I do in my listener thread is update a protected member that houses the data. Here's an example of what I'm doing (note that I don't have the part of the code that calls the AsyncTask, but it's fired from a listener):

public class main extends Activity() {

 protected LinkedList<HashMap<String, String>> adapterDataList = new LinkedList<HashMap<String, String>>();
 protected MyDataObject dataObject;
 protected SimpleAdapter dataAdapter;

 @Override
 public void onCreate(Bundle savedInstanceState) {

     //call parent oncreate
     super.onCreate(savedInstanceState);

  //display the main form
  setContentView(R.layout.main);

  //get a handle on the score list view elements
  ListView dataList = (ListView)(findViewById(R.id.datalist));

  //link the adapter and the data source
  dataAdapter = new SimpleAdapter(this, adapterDataList, R.layout.row, new String[]{"name","address"}, new int[]{R.id.username,R.id.address});

  dataList.setAdapter(dataAdapter);

 }

 protected void refreshData() {
  adapterDataList.clear();
  Iterator<MyData> iter = MyDataObject.iterator();
  while(iter.hasNext()) {
   HashMap<String, String> item = new HashMap<String, String>()
   item.put("name", iter.name);
   item.put("address", iter.address);
   adapterDataList.add(item);
  }

  dataAdapter.notifyDataSetChanged();
 }

 private class DataTask extends AsyncTask<Data, Void, Data> {
  protected void onPostExecute(Data data) {
   dataObject = data;
   runOnUiThread (new Runnable() { public void run() {
    refreshScores();
   }});
  }
 }

 ...
}

Does anyone have any pointers or ideas as to why I'm getting this exception? Any help is much appreciated.

edit Here are the layout files, as requested: main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ptl="http://schemas.android.com/apk/res/com.mod0.pubtrivialive"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/datalistcontainer">

    <ListView android:id="@+id/datalist" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

</LinearLayout>

row.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal"
  android:paddingBottom="6dip"
  android:paddingTop="4dip">

  <TextView android:id="@+id/name"
  android:layout_width="80dip"
  android:layout_height="wrap_content" />

  <TextView android:id="@+id/address"
  android:layout_height="wrap_content"
  android:layout_weight="1" />

</LinearLayout>
A: 

This doesn't look right dataList.clear();. Are you sure you're meaning to call clear on dataList and not adapterDataList?

Falmarri
Sorry, I edited again. I've changed variable names to make things clearer and messed that part up. I add each item created inside the while loop to the dataList and then call notifyDataSetChanged() on the adapter. I call dataList.clear() before the while loop to remove the old data so that I can populate it with the new data.
Matt
Are you set on using `SimpleAdapter`? I would recommend making your own adapter class that extends either `BaseAdapter` or `ArrayAdapter`
Falmarri
I could do that; I was just hoping to keep things, er, simple. :) I'll report back if I can use a custom adapter.
Matt
Normally when you have to add/remove views, modify stuff and generally muck with the list, you should probably implement your own stuff.
Falmarri
Implementing my own view did help out. It forced me to get in there and really figure out how things work. FWIW, the reason the inflater was throwing an exception was because the address TextView didn't have a width attribute, which is required. I only found this out by doing a try/catch in the adapter getView method and logging the exception, which was only possible because I created my own adapter. Thanks for the tips!
Matt
Oh, well. I'm glad I could help, but I didn't even really read the exception >_<. You should post an answer about not having the required attributes in an answer and then accept that. That's a more relevant answer.
Falmarri