【问题标题】:How to clear the views which are held in the ListView's RecycleBin?如何清除 ListView 回收站中的视图?
【发布时间】:2012-08-21 06:08:17
【问题描述】:

在 Android 的 ListView 小部件中,ListView 将保存从内部类 RecycleBin 中适配器的 getView 方法获得的视图。

如何清除RecycleBin 中的视图并强制ListView 重新创建所有子视图。

【问题讨论】:

  • 如果您使用的是convertView,请尽量不要使用它。您应该对布局进行膨胀,然后将其作为 View 实例返回。
  • 使用ListView 的唯一目的是重用子视图。为什么要逆流而上?
  • 我从你那里得到了一个方法,谢谢!

标签: android android-listview


【解决方案1】:

致电 invalidate()invalidateViews() 对我来说并没有成功(如正确答案中所述)。回收的视图仍然存储在 ListView 中。我不得不深入研究 Android 源代码以找到解决方案。我检查了很多方法,包括 ListView 类的 setAdapter() 方法(Android API 15):

@Override
public void setAdapter(ListAdapter adapter) {

    // ...
    mRecycler.clear();
    // ...

}

如您所见,设置适配器会清除回收器,该回收器将所有回收的视图保存在列表视图中。您不必创建新的适配器,设置相同的适配器就足以清除列表视图中的回收视图列表:

Adapter adapter = listview.getAdapter ();
// ... Modify adapter ... do anything else you need to do
// To clear the recycled views list :
listview.setAdapter ( adapter );

【讨论】:

  • 你是正确的设置适配器确实清除了回收器。正如我在回答中所说,我记得读过有关 invalidate() 清除 ListView 的信息(不是 100% 确定)。
  • +1 这确实是一个巧妙的技巧,可惜在这里无效无效。
  • 很好,谢谢。我需要在 Android 5.0 上使用此功能,即使在适配器中的项目已替换并且列表已刷新,但在单击某个项目后,循环视图上的涟漪效果仍在动画中。
  • 同样的事情也适用于 RecyclerView。设置相同的适配器将导致 Recycler 重新创建所有视图。我使用它是因为 Recycler 中视图的高度发生了变化。
  • Android 有时真的让我很生气,我们没有理由坐在这里尝试所有这些选项并失败。
【解决方案2】:

如果我没记错的话,在 ListView 小部件上调用 invalidate 将清空当前存储的 Views 的缓存。由于潜在的性能问题,我建议不要清空 ListView 的视图缓存。

如果您不打算使用convertView 项目,那么您最终将不得不每次都构建行视图(导致每次用户滚动时都会构建大量对象)+ 占用的额外内存来自RecycleBin 的回收视图,无论如何都不会使用。

【讨论】:

  • 是的,由于潜在的 oom 问题,我将使用 convertView。但在某些特殊情况下,我需要更改listview的childview类的类型,所以我必须销毁recyclebin中的所有视图并调用getview方法重新创建子视图。
  • @zangtao 在这种情况下,我认为您需要致电invalidate
  • 调用 invalidateinvalidateViews 没有成功。
【解决方案3】:

ListView - reclaimViews(List<View>) 中有一个特殊的方法。它将当前正在使用和回收站中的所有项目移动到指定列表。小部件将在下次渲染之前从Adapter 请求新视图。

如果项目结构没有太多更改,您可以使用回收的视图,或者完全废弃它们。例如,当用户更改选择颜色时,我正在使用此方法动态更新项目的背景可绘制对象。

【讨论】:

    【解决方案4】:

    从 ArrayList 或您在自定义适配器中使用的数据结构中删除回收站对象,并调用适配器的 notifyDataSetChanged 方法。

    【讨论】:

      【解决方案5】:

      在我看来,@nekavally 提供了最好的解决方案。我有一个ListView 和一个SimpleCursorAdapter。有时我需要更改列表项的大小。但是由于适配器回收视图,它们可能会以错误的方式出现。所以我只是在回收回收视图后调用mListView.invalidateViews(),它工作得很好。

      startAnimation(initialHeight, finalHeight, duration, new ValueAnimator.AnimatorUpdateListener() {
                          @Override
                          public void onAnimationUpdate(ValueAnimator animation) {
                              childView.getLayoutParams().height = 
                                      (Integer) animation.getAnimatedValue();
                              childView.requestLayout();
      
                              if (animation.getAnimatedFraction() == 1f) {
                                  mListView.reclaimViews(new ArrayList<View>());
                                  mListView.invalidateViews();
                              }
                          }
                      });
      

      【讨论】:

        猜你喜欢
        • 2020-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多