38

ListView正在使用 的扩展BaseAdapter,我无法让它正确刷新。当我刷新时,旧数据似乎在新数据之上,直到发生滚动事件。旧行绘制在新行之上,但是当我开始滚动时旧行消失了。

我试过打电话给invalidateViews(),notifyDataSetChanged()notifyDataSetInvalidated()。我的代码看起来像:

private void updateData()
{
   List<DataItems> newList = getNewList();

   MyAdapter adapter = new MyAdapter(getContext());
   //my adapter holds an internal list of DataItems
   adapter.setList(newList);
   mList.setAdapter(adapter);
   adapter.notifyDataSetChanged();
   mList.invalidateViews();
}
4

9 回答 9

60

对于那些仍然有问题的人,我是这样解决的:

List<Item> newItems = databaseHandler.getItems();
ListArrayAdapter.clear();
ListArrayAdapter.addAll(newItems);
ListArrayAdapter.notifyDataSetChanged();
databaseHandler.close();

我先清除了适配器中的数据,然后添加了新的项目集合,然后才设置notifyDataSetChanged(); 这个一开始我并不清楚,所以我想指出这一点。请注意,如果不调用notifyDataSetChanged()视图,则不会更新。

于 2012-09-30T16:39:59.073 回答
13

据我了解,如果你想在数据发生变化时立即刷新 ListView,你应该调用notifyDataSetChanged().RunOnUiThread()

private void updateData() {
    List<Data> newData = getYourNewData();
    mAdapter.setList(yourNewList);

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
                mAdapter.notifyDataSetChanged();
        }
    });
}
于 2012-02-29T01:47:56.957 回答
12

您不必创建新适配器来更新 ListView 的内容。只需将您的适配器存储在一个字段中并使用以下代码更新您的列表:

mAdapter.setList(yourNewList);
mAdapter.notifyDataSetChanged();

为了澄清这一点,您的 Activity 应如下所示:

private YourAdapter mAdapter;

protected void onCreate(...) {

    ...

    mAdapter = new YourAdapter(this);
    setListAdapter(mAdapter);

    updateData();
}

private void updateData() {
    List<Data> newData = getYourNewData();
    mAdapter.setList(yourNewList);
    mAdapter.notifyDataSetChanged();
}
于 2011-02-04T23:40:51.623 回答
4

我认为用不同的数据重新填充同一个适配器将是更多或最好的技术。将此方法放在带有正确参数的适配器类中(在我的情况下,您要显示为名称的数据列表)在您使用更新的列表(在我的情况下为名称)更新列表数据的地方调用此方法

public void refill(ArrayList<BeanDatabase> names) {
    list.clear();
    list.addAll(names);
    list.notifyDataSetChanged();
}

如果您更改适配器或在列表更新时一次又一次地设置适配器,那么强制关闭错误肯定会在某些时候导致问题。(错误:列表数据已更新,但适配器未通知列表视图)

于 2012-02-16T05:37:16.777 回答
3

我也尝试过 invalidate()、invalidateViews()、notifyDataSetChanged()。它们都可能在某些特定情况下起作用,但在我的情况下它并没有起作用。

就我而言,我必须在列表中添加一些新行,但它不起作用。创建一个新的适配器解决了这个问题。

在调试时,我意识到数据在那里但没有渲染。如果 invalidate() 或 invalidateViews() 没有呈现(它应该呈现),我不知道会发生什么。

创建一个新的 Adapter 对象来刷新修改的数据似乎不是一个坏主意。它绝对有效。唯一的缺点可能是为您的适配器分配新内存所消耗的时间,但假设 Android 系统足够智能并且能够保持高效,这应该没问题。

如果你把它排除在等式之外,流程几乎与调用 notifyDataSetChanged 相同。从某种意义上说,在任何一种情况下都会调用同一组适配器函数。

因此,我们并没有失去太多,而是获得了很多。

于 2011-09-08T08:04:37.213 回答
2

我正在使用 invalidateViews() 做同样的事情,这对我有用。如果您希望它立即失效,您可以在调用 invalidateViews 后尝试调用 postInvalidate。

于 2011-02-04T23:36:20.093 回答
2

通过以下代码更新 ListView 的内容:

private ListView listViewBuddy;
private BuddyAdapter mBuddyAdapter;
private ArrayList<BuddyModel> buddyList = new ArrayList<BuddyModel>();

onCreate()

listViewBuddy = (ListView)findViewById(R.id.listViewBuddy);
mBuddyAdapter = new BuddyAdapter();
listViewBuddy.setAdapter(mBuddyAdapter);

onDataGet(在网络服务调用或从本地数据库或其他):

mBuddyAdapter.setData(buddyList);
mBuddyAdapter.notifyDataSetChanged();

基础适配器

private class BuddyAdapter extends BaseAdapter { 

    private ArrayList<BuddyModel> mArrayList = new ArrayList<BuddyModel>();
    private LayoutInflater mLayoutInflater= (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    private ViewHolder holder;

    public void setData(ArrayList<BuddyModel> list){
        mArrayList = list;
    }

    @Override
    public int getCount() {
        return mArrayList.size();
    }

    @Override
    public BuddyModel getItem(int position) {
        return mArrayList.get(position);
    }

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

    private class ViewHolder {
        private TextView txtBuddyName, txtBuddyBadge;

    }
    @SuppressLint("InflateParams")
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = mLayoutInflater.inflate(R.layout.row_buddy, null);
            // bind views
            holder.txtBuddyName = (TextView) convertView.findViewById(R.id.txtBuddyName);
            holder.txtBuddyBadge = (TextView) convertView.findViewById(R.id.txtBuddyBadge);

            // set tag
            convertView.setTag(holder);
        } else {
            // get tag
            holder = (ViewHolder) convertView.getTag();
        }

        holder.txtBuddyName.setText(mArrayList.get(position).getFriendId());

        int badge = mArrayList.get(position).getCount();
        if(badge!=0){
            holder.txtBuddyBadge.setVisibility(View.VISIBLE);
            holder.txtBuddyBadge.setText(""+badge);
        }else{
            holder.txtBuddyBadge.setVisibility(View.GONE);
        }   

        return convertView;
    }
}

每当您想更新 Listview时,只需调用以下两行代码:

 mBuddyAdapter.setData(Your_Updated_ArrayList);
 mBuddyAdapter.notifyDataSetChanged();

完毕

于 2015-07-08T09:31:58.623 回答
1

只有这对我每次都有效,请注意我不知道它是否会导致任何其他并发症或性能问题:

private void updateListView(){
        listview.setAdapter(adapter);
    }
于 2015-08-25T14:30:22.490 回答
1

另一种简单的方法:

//In your ListViewActivity:
public void refreshListView() {
    listAdapter = new ListAdapter(this);
    setListAdapter(listAdapter);
}
于 2016-09-08T16:28:03.843 回答