Android:如何刷新ListView内容?

发布于 2024-10-16 08:06:23 字数 596 浏览 2 评论 0原文

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

My ListView is using an extension of BaseAdapter, I can not get it to refresh properly. When I refresh, it appears that the old data draws on top of the new data, until a scroll event happens. The old rows draw on top of the new rows, but the old rows disappear when I start scrolling.

I have tried calling invalidateViews(), notifyDataSetChanged(), and notifyDataSetInvalidated(). My code looks something like:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

以可爱出名 2024-10-23 08:06:23

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

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

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

To those still having problems, I solved it this way:

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

I first cleared the data from the adapter, then added the new collection of items, and only then set notifyDataSetChanged();
This was not clear for me at first, so I wanted to point this out. Take note that without calling notifyDataSetChanged() the view won't be updated.

蓝咒 2024-10-23 08:06:23

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

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

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

In my understanding, if you want to refresh ListView immediately when data has changed, you should call notifyDataSetChanged() in RunOnUiThread().

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

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
                mAdapter.notifyDataSetChanged();
        }
    });
}
葬花如无物 2024-10-23 08:06:23

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

You don't have to create a new adapter to update your ListView's contents. Simply store your Adapter in a field and update your list with the following code:

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

To clarify that, your Activity should look like that:

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();
}
耳根太软 2024-10-23 08:06:23

我认为用不同的数据重新填充相同的适配器将是更好或最好的技术。
将此方法放入您的 Adapter 类中并使用正确的参数(在我的例子中您想要显示为名称的数据列表)
在您用更新的列表更新列表数据的地方调用此方法(在我的例子中为名称)

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

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

I think refilling the same adapter with different data would be more or most better technique.
Put this method in your Adapter class with right argument (the data list you want to display as names in my case)
Call this where u update the data of list with updated list (names in my case)

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

If you change the adapter or set the adapter again and again on when the list updates, then force close error would surely cause problems at some point. (Error:List data been updated but adapter doesn't notify the List View)

晨敛清荷 2024-10-23 08:06:23

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

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

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

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

如果您将其排除在外,则流程几乎与调用notifyDataSetChanged 相同。从某种意义上说,在这两种情况下都会调用同一组适配器函数。

所以我们并没有失去太多,反而得到了很多。

I too have tried invalidate(), invalidateViews(), notifyDataSetChanged(). They all might work in some particular contexts but it did not do the job in my case.

In my case, I had to add some new rows to the list and it just does not work. Creating a new adapter solved the issue.

While debugging, I realized that the data was there but just not rendered. If invalidate() or invalidateViews() does not render (which it is supposed to), I don't know what would.

Creating a new Adapter object to refresh modified data does not seem to be a bad idea. It definitely works. The only downside could be the time consumed in allocating new memory for your adapter but that should be OK assuming the Android system is smart enough and takes care of that to keep it efficient.

If you take this out of the equation, the flow is almost same as to calling notifyDataSetChanged. In the sense, the same set of adapter functions are called in either case.

So we are not losing much but gaining a lot.

清风夜微凉 2024-10-23 08:06:23

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

I'm doing the same thing using invalidateViews() and that works for me. If you want it to invalidate immediately you could try calling postInvalidate after calling invalidateViews.

当梦初醒 2024-10-23 08:06:23

通过以下代码更新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(在Web服务调用之后或从本地数据库或其他方式):

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

BaseAdapter< /strong>:

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();

完成

Update ListView's contents by below code:

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 (After webservice call or from local database or otherelse):

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

Whenever you want to Update Listview just call below two lines code:

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

Done

千寻… 2024-10-23 08:06:23

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

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

Only this works for me everytime, note that I don't know if it causes any other complications or performance issues:

private void updateListView(){
        listview.setAdapter(adapter);
    }
我不咬妳我踢妳 2024-10-23 08:06:23

另一种简单的方法:

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

Another easy way:

//In your ListViewActivity:
public void refreshListView() {
    listAdapter = new ListAdapter(this);
    setListAdapter(listAdapter);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文