在Android的ListView
窗口小部件中,ListView
将保存内部类getView
中适配器的RecycleBin
方法获取的视图。
如何清除RecycleBin
中的视图并强制ListView
重新创建所有子视图。
答案 0 :(得分:42)
致电 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 );
答案 1 :(得分:4)
如果我没记错的话,invalidate
窗口小部件上ListView
的调用将清空当前存储的Views
缓存。我建议不要因为潜在的性能问题而清空ListView
的视图缓存。
如果您不打算使用convertView
项,那么每次都必须构建行视图(每次用户滚动时都会构造很多对象)+额外的来自RecycleBin
的回收视图占用的内存,无论如何都不会被使用。
答案 2 :(得分:2)
ListView
- reclaimViews(List<View>)
中有一种特殊方法。它将当前正在使用的所有项目和回收站中的所有项目移动到指定列表。在下次渲染之前,窗口小部件将为Adapter
的项目请求新视图。
如果项目结构没有太多变化,您可以使用回收的视图,或者完全废弃它们。例如,当用户更改选择颜色时,我使用此方法动态更新项目的背景可绘制。
答案 3 :(得分:0)
从ArrayList中删除回收站的对象或您在自定义适配器中使用的数据结构,并调用适配器的notifyDataSetChanged
方法。
答案 4 :(得分:0)
在我看来,@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();
}
}
});