Android:如何刷新ListView内容?

时间:2011-02-04 23:00:05

标签: android listview android-adapter

我的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();
}

9 个答案:

答案 0 :(得分:59)

对于仍有问题的人,我这样解决了:

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

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

答案 1 :(得分:12)

据我了解,如果您想在数据发生变化时立即刷新ListView,则应在notifyDataSetChanged()中致电RunOnUiThread()

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

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
                mAdapter.notifyDataSetChanged();
        }
    });
}

答案 2 :(得分:11)

您不必创建新的适配器来更新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();
}

答案 3 :(得分:3)

我也尝试过invalidate(),invalidateViews(),notifyDataSetChanged()。它们都可能在某些特定环境中起作用,但在我的情况下它不起作用。

在我的情况下,我不得不在列表中添加一些新行,它只是不起作用。创建新适配器解决了这个问题。

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

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

如果你从方程式中取出这个,那么流程几乎与调用notifyDataSetChanged相同。从某种意义上说,在任何一种情况下都会调用相同的适配器函数集。

所以我们并没有太多损失,而是获得了很多。

答案 4 :(得分:3)

我认为用不同的数据重新填充相同的适配器将是更多或更好的技术。 将此方法放在具有right参数的Adapter类中(在我的情况下,您要显示为名称的数据列表) 调用此处更新列表数据的更新列表(在我的情况下为名称)

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

如果在列表更新时更改适配器或反复设置适配器,则强制关闭错误肯定会在某些时候引起问题。 (错误:列表数据已更新,但适配器未通知列表视图)

答案 5 :(得分:2)

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

答案 6 :(得分:1)

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

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

<强>的onCreate()

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

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

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;
    }
}

<强> BaseAdapter

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

每当您希望更新Listview 时,只需拨打以下两行代码:

public boolean isExtraHour(final ZonedDateTime time) {
    final ZoneOffsetTransition dayTransition = time.getZone().getRules()
            .getTransition(time.toLocalDateTime());

    return dayTransition != null && dayTransition.isOverlap() && dayTransition.getInstant()
            .equals(time.toInstant());
}

完成

答案 7 :(得分:1)

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

private void updateListView(){
        listview.setAdapter(adapter);
    }

答案 8 :(得分:0)

另一种简单方法:

//In your ListViewActivity:
public void refreshListView() {
    listAdapter = new ListAdapter(this);
    setListAdapter(listAdapter);
}