【问题标题】:Android ListView - difference between adapter.notifyDataSetChanged and using new adapterAndroid ListView - adapter.notifyDataSetChanged 和使用新适配器之间的区别
【发布时间】:2014-06-09 15:10:16
【问题描述】:

我的问题是基于这篇文章。

Android. How does notifyDataSetChanged() method and ListViews work?

我在各种文章中读到,要刷新 listView,您必须调用 notifyDataSetChanged() 而不是 listView.setAdapter(new Adapter(....));,因为第二种方法成本太高且影响性能

上述问题的答案是adapter.notifyDataSetChanged() 影响当前在屏幕上可见的视图。因此,getView() 的调用次数与当前显示的项目数一样多。

但在将新适配器分配给 listView 时,getView() 的调用次数也相同。

那么调用adapter.notifyDataSetChanged()listView.setAdapter(new Adapter(....)); 有什么区别呢?

【问题讨论】:

    标签: android android-listview listview-adapter


    【解决方案1】:

    当您调用notifyDataSetChanged() 时,getView() 的调用次数相同。但是,由于适配器是相同的,因此这些视图可以重复使用(即作为convertView 传递)。

    在提供新适配器时无法做到这一点,因为ListView 无法确定新适配器使用相同的布局。所以回收器被清除了,所有的行都必须从头开始创建(这比重复使用它们要昂贵得多)。

    (如果您忽略提供的 convertView 并始终创建/扩充新视图,则此性能点没有实际意义——但这无论如何都是个坏主意)。

    【讨论】:

    • 另一个重要的区别是你也将失去使用稳定 id 来保持滚动位置的能力...... ListView 不会知道新适配器的稳定 id 是否与旧适配器,它会将您的用户送回列表顶部。
    • 所以(除了顶部的滚动)只有当我在 getView() 方法中使用 ViewHolder 来重用视图时才有区别?
    • 区别实际上是你是否使用提供的convertView(即总是忽略它的值并创建/扩展一个新视图)。 ViewHolder 模式只是对此的进一步优化。编辑答案以包含这一点。
    【解决方案2】:

    setAdapter()会清空用来保存为convertView的scrap heap,还会设置一个新的adapter,然后requestLayout()。

    但是,notifyDataSetChanged()只是requestLayout()。所以废品堆还在,当getView()发生时,如果废品堆包含convertView就不会为空,所以不需要膨胀。

    所以,当数据发生变化时,调用 notifyDataSetChanged() 而不是 setAdapter() 效率更高。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-11
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      相关资源
      最近更新 更多