Android:如何刷新ListView的内容?
我的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(); }
对于那些还有问题的人,我这样解决了:
List<Item> newItems = databaseHandler.getItems(); ListArrayAdapter.clear(); ListArrayAdapter.addAll(newItems); ListArrayAdapter.notifyDataSetChanged(); databaseHandler.close();
我首先从适配器中清除了数据,然后添加了新的项目集合,然后才设置了notifyDataSetChanged();
起初我不清楚,所以我想指出这一点。 请注意,不调用notifyDataSetChanged()
视图将不会更新。
您不必创build一个新的适配器来更新您的ListView的内容。 只需将您的适配器存储在一个字段中,并使用以下代码更新您的列表:
mAdapter.setList(yourNewList); mAdapter.notifyDataSetChanged();
为了澄清,你的活动应该是这样的:
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(); }
在我的理解,如果你想立即刷新ListView数据已经改变,你应该在RunOnUiThread()
调用RunOnUiThread()
。
private void updateData() { List<Data> newData = getYourNewData(); mAdapter.setList(yourNewList); runOnUiThread(new Runnable() { @Override public void run() { mAdapter.notifyDataSetChanged(); } }); }
我也试过invalidate(),invalidateViews(),notifyDataSetChanged()。 他们都可能在某些特定的环境下工作,但是对我而言,这并没有完成这项工作。
在我的情况下,我不得不添加一些新的行到列表,它只是不工作。 创build一个新的适配器解决了问题。
在debugging时,我意识到数据在那里,但没有呈现。 如果invalidate()或invalidateViews()不呈现(它应该),我不知道会是什么。
创build一个新的Adapter对象来刷新修改后的数据似乎不是一个坏主意。 它绝对有效。 唯一的缺点可能是为你的适配器分配新的内存所花费的时间,但假设Android系统足够聪明并且保持它的效率,这应该是确定的。
如果不考虑这一点,则stream程与调用notifyDataSetChanged几乎相同。 从某种意义上讲,在任何一种情况下都会调用相同的一组适配器函数。
所以我们没有太大的损失,而是获得了很多。
我认为用不同的数据重新填充同一个适配器会是更好或者更好的技术。 把这个方法放在你的Adapter类中,使用正确的参数(你想在我的例子中显示的数据列表名称)调用这个你更新列表的数据与更新列表(我的例子中的名称)
public void refill(ArrayList<BeanDatabase> names) { list.clear(); list.addAll(names); list.notifyDataSetChanged(); }
如果更改适配器或在列表更新时一次又一次地设置适配器,那么强制closures错误肯定会在某个时候造成问题。 (错误:列表数据已更新,但适配器不通知列表视图)
我正在做同样的事情使用invalidateViews()和我的作品。 如果你想立即失效,你可以尝试调用invalidateViews后调用postInvalidate。
通过以下代码更新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 (在webservice调用或从本地数据库或其他):
mBuddyAdapter.setData(buddyList); mBuddyAdapter.notifyDataSetChanged();
BaseAdapter :
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();
完成
只有这个对我来说每次都适用,请注意,我不知道是否会导致任何其他复杂性或性能问题:
private void updateListView(){ listview.setAdapter(adapter); }
另一个简单的方法
//In your ListViewActivity: public void refreshListView() { listAdapter = new ListAdapter(this); setListAdapter(listAdapter); }