重建ListView适配器或清除并重新填充哪个更好?

6
如果我有一个带有 CustomAdapter 的 ListView,假设我有这个 refresh() 方法来刷新列表并显示新的结果,那么我应该:
  1. 在初始化时调用 new CustomAdapter(...),每次调用 refresh() 时使用 adapter.clear() 和 adapter.add(...)。
  2. 每次调用 refresh() 时都调用 new CustomAdapter(...)。
基本上,我的问题是,重新创建适配器加载新结果是否更好,还是清除现有适配器中的结果并添加整个列表到其中更好?
2个回答

4
如果您打算按照适配器的意图使用它们,那么您需要更新适配器的数据并在其上调用notifyDataSetChanged()
如果您查看像ArrayAdapter这样的API,它有许多方法,如clear()add()addAll()notifyDataSetChanged()等,旨在引导您朝着特定API的使用方式前进。
通过使用这些方法,不仅可以使您的代码符合其预期的使用方式,而且还可以使其更易于理解,并且对于试图理解您的代码的其他人来说更加熟悉。
因此,基本上只有在最后一种情况下才需要重新创建适配器。

但是我认为使用add()会慢得多(尚未证明)。将数据列表作为参数传递到其构造函数中实际上加快了进程(个人经验)。所以我真的不知道... - raybaybay
但是在创建新适配器之后,您必须调用ListView#setAdapter(),它本身也有开销:https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/ListView.java - JDJ

2
在处理it技术方面,建议您调用原始适配器中的 notifyDataSetChanged() 方法而不是设置一个新的适配器。 这么做的原因是出于性能考虑:为了避免在滚动时创建新的item视图,ListView使用视图回收机制。如果您设置了一个新的适配器,则这些已经回收的视图将被丢弃,这意味着它们必须从头开始重新创建以供下一次布局流程使用。请查看ListView.setAdapter()代码来了解更多信息。
@Override
public void setAdapter(ListAdapter adapter) {
    if (mAdapter != null && mDataSetObserver != null) {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
    }

    resetList();
    mRecycler.clear();

    ...

这是完全合理的行为,因为ListView假定新适配器使用的视图与先前适配器返回的视图不兼容(无论如何,它不能假定它们将兼容)。所以它们被丢弃。
因此,如果每次设置一个新适配器,您会产生不必要的性能损耗(重新创建所有当前视图)。
另外,如果您编写了一个自定义适配器,您不一定需要单独调用add()(就像ArrayAdapter一样)。您只需用新的内部数据集替换旧的,并在之后调用notifyDataSetChanged()即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接