8
votes

I've got some troubles with notifyDataSetChanged() of a BaseAdapter. This method is called in refreshItems() and shall update the BaseAdapter of my ListActivity. On calling notifyDataSetChanged() nothing happens until I scroll down the ListView for example with the arrow keys. Somehow the modified getView() method also is not called. Maybe you can give me a hint - thanks! :)

public class WinampControlClientPlaylist extends ListActivity {

static WinampControlClientPlaylist activity = null;

static EfficientAdapter adapter = null;


static class EfficientAdapter extends BaseAdapter {


    public EfficientAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
    }

    private LayoutInflater mInflater;

    @Override
    public int getCount() {
        return Settings.playlistlength;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;


        if (convertView == null) 
        {
            holder = new ViewHolder();

            convertView = mInflater.inflate(R.layout.listview, null);

            holder.text = (TextView) convertView.findViewById(R.string.playlist_title);
            holder.image = (ImageView) convertView.findViewById(R.string.playlist_play);

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


        holder.text.setText(Settings.playlist[position]);

        if (position == Settings.playlistPosition)
        {
            holder.text.setTypeface(null, Typeface.ITALIC);
            holder.image.setVisibility(0);
        }
        else
        {
            holder.text.setTypeface(null, Typeface.NORMAL);
            holder.image.setVisibility(4);
        }


        return convertView;
    }


    static class ViewHolder {
        TextView text;
        ImageView image;
    }

    @Override
    public Object getItem(int position) {
        return Settings.playlist[position];
    }
}




void initialize()
{
    adapter = new EfficientAdapter(this);
    setListAdapter(adapter);

    //registerForContextMenu(getListView());
}


@Override
public void onResume()
{
    super.onResume();

    // REFRESH PLAYLIST
    if (getListAdapter() == null && Settings.playlist != null)
        initialize();
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.playlist);

    activity = this;
}

static void refreshItems()
{
    try {
        adapter.notifyDataSetChanged();
    } catch (Exception e) {}

}

}

9
well, maybe i dont understand your question but a ListView will update if their dataset has changed, and the way to notify that is calling notifyDataSetChanged() to the ListView. But here i dont see where you change the dataset, Settings are changing in other thread or place?Franco
yeah right, another Activity calls Settings.playlistPosition = newNumber and WinampControlClientPlaylist.refreshItems(); But when this happens the ListView isn't updated. I only see changes when I press arrow up/down in the emulator afterwards.martin

9 Answers

9
votes

I had the same problem (ListView updates only when i scroll it, even notifyDataSetChanged didn't help). i solve it this way: just try to do your "view modifications" in thread which creates your user interface i.e.

activity.runOnUiThread(new Runnable() {         
        public void run() {
              //do your modifications here

              // for example    
              adapter.add(new Object());
              adapter.notifyDataSetChanged()  
        }
});
4
votes

Try calling invalidate() on your ListView.

4
votes

As Franco pointed out, notifyDataSetChanged() is used to tell the ListView that the contents of its adapter have changed, not that it needs to redraw itself. You are just changing a setting that affects how something is rendered. Try calling refreshDrawableState to tell the list to redraw.

0
votes

I had the same issue, and the solution for me was to call requestLayout() on the ListView.

0
votes

I think there may be some problems with the adapter; maybe it's not set.

In my experience, there was always some kind of reason which prevented the listview (and adapter) to update.

0
votes

call AbsListView.invalidateViews() on your listview after BaseAdapter.notifyDataSetChanged()

0
votes

I encountered the same problem, and I tried to call notifyDataSetChanged() on the adapter. Besides, I also tried to call refreshDrawableState(), invalidateViews() on the view and none of those worked. All these methods are called in the UI thread. Then I found this How to clear the views which are held in the ListView's RecycleBin? . Finally setAdapter() worked, only if I create a new adapter.

0
votes

The main reason behind this is the wrong reference of the adapter on which you are calling notifyDataSetChanged();

I think you need to make sure that you are creating adapter object once and call notifyDataSetChanged() on the same object.

You can debug the object reference value at creating time of adapter object and when you are calling notifyDataSetChanged() method.

0
votes
Why it works in first code ?

--- Because you are setting the values to temp List and passing it the adapter and it shows it into listview.

Why not work in second code ?

--- Because you are setting temp to adapter far before you set value into temp second,your adapter class might not getting the updated value when you set new value to temp ..that because temp is not public or not at class level or not static.. Put the temp declaration at root level and try.

And please show your full code as much as required and Logcat if you getting any warnings than also.