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();
}
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
对于那些仍然有问题的人,我这样解决了:
我首先清除适配器中的数据,然后添加新的项目集合,然后才设置
notifyDataSetChanged();
一开始我并不清楚,所以我想指出这一点。请注意,如果不调用
notifyDataSetChanged()
,视图将不会更新。To those still having problems, I solved it this way:
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.在我的理解中,如果你想在数据发生变化时立即刷新ListView,你应该在
RunOnUiThread()
中调用notifyDataSetChanged()
。In my understanding, if you want to refresh ListView immediately when data has changed, you should call
notifyDataSetChanged()
inRunOnUiThread()
.您不必创建新的适配器来更新 ListView 的内容。只需将您的适配器存储在一个字段中,并使用以下代码更新您的列表:
为了澄清这一点,您的活动应该如下所示:
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:
To clarify that, your Activity should look like that:
我认为用不同的数据重新填充相同的适配器将是更好或最好的技术。
将此方法放入您的 Adapter 类中并使用正确的参数(在我的例子中您想要显示为名称的数据列表)
在您用更新的列表更新列表数据的地方调用此方法(在我的例子中为名称)
如果您在列表更新时更改适配器或一次又一次地设置适配器,那么强制关闭错误肯定会在某些时候导致问题。 (错误:列表数据已更新,但适配器未通知列表视图)
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)
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)
我也尝试过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.
我正在使用 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.
通过以下代码更新ListView的内容:
onCreate():
onDataGet(在Web服务调用之后或从本地数据库或其他方式):
BaseAdapter< /strong>:
每当你想要更新Listview只需调用下面两行代码:
完成
Update ListView's contents by below code:
onCreate():
onDataGet (After webservice call or from local database or otherelse):
BaseAdapter:
Whenever you want to Update Listview just call below two lines code:
Done
只有这每次都对我有效,请注意,我不知道它是否会导致任何其他并发症或性能问题:
Only this works for me everytime, note that I don't know if it causes any other complications or performance issues:
另一种简单的方法:
Another easy way: