在我过去的一个项目中,我实施了“Time Picker Carousel”。它基于HorizontalScrollView
。用户可以在滚动此视图时选择时间。时间值是根据HorizontalScrollView
的X-Offset计算的。
我想在github上分享这个项目,但在清理代码时我发现了一些性能不佳问题。
HorizontalScrollView
填充了自定义ArrayAdapter
。 getView()
Holder
使用convertView
。我认为它可能在ListView
中作为适配器工作,因此只有可见项才会被销毁并重新使用它们。相反,所有项目都被渲染!!! (在我的情况下是1008!)我自己添加它们(代码示例中为#1),但即使我尝试添加更少,但删除(和回收)旧的逻辑不起作用,或者我是想念什么?
所以我的基本问题是:我需要更改什么才能使我的适配器的行为类似于ListView
?
remove
函数,但这从未调用过(不知何故逻辑,因为我只是添加)ArrayAdapter<String>
欢迎任何想法,链接!
请不要建议使用ListView
。我们决定使用HorizontalScrollView
因为回调以及我们在布局中已经有ListView
的事实。
HorizontalScrollView
InfiniteTimeScrubberHorizontalView extends HorizontalScrollView{
...
public void setAdapter(Context context, TimeScrubberListAdapter mAdapter) {
this.mAdapter = mAdapter;
try {
fillViewWithAdapter(mAdapter);
} catch (ZeroChildException e) {
e.printStackTrace();
}
}
private void fillViewWithAdapter(TimeScrubberListAdapter mAdapter) {
//...
ViewGroup parent = (ViewGroup) getChildAt(0);
parent.removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
//#1: Here: ALL views are added
parent.addView(mAdapter.getView(i, null, parent));
}
}
Adpater
public class TimeScrubberListAdapter extends ArrayAdapter<String> {
//...
private ArrayList<String> list; //list from 0:00,0:30...23:00,23:30
final static int MAXIMUM_DAYS = 21
@Override
public int getCount() {
return list.size() * MAXIMUM_DAYS;
}
@Override
public String getItem(int position) {
return list.get(position % list.size());
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
RelativeLayout layout;
if (convertView == null) {
layout = (RelativeLayout) View.inflate(context, layoutId, null);
holder = new Holder();
holder.title = (TextView) layout.findViewById(R.id.epg_item_text);
layout.setTag(holder);
} else {
layout = (RelativeLayout) convertView;
view = layout;
holder = (Holder) layout.getTag();
}
layout.setLayoutParams(mLP);
String timeValue = getItem(position);
holder.title.setText(timeValue);
return layout;
}
//...
@Override
public void remove(String object) {
//not called...some how logic, because i do not remove an item
super.remove(object);
}
答案 0 :(得分:15)
我想也许你会混淆视图和适配器之间渲染的逻辑。使用适配器不会导致视图回收行为。 ListView
本身及其父级AbsListView
实现了视图回收行为。 ListView
需要适配器才能正确填充屏幕上显示的视图,但是实际选择要显示哪些视图以及何时以及如何回收这些视图的逻辑不在适配器中所有
如果您查看HorizontalScrollView
和ListView
的源代码,您会发现它们截然不同。它们不同的方向不同。
因此,它的长短之处在于,您无法使用HorizontalScrollView
甚至是简单的后代来获取您正在寻找的视图回收。如果您想要查看回收,请查看RecyclerView
。
答案 1 :(得分:2)
ScrollView将所有子视图保留在内存中,因此在使用它们时性能问题很常见。
为什么不使用一些开源的HorizontalListView库。 在搜索时,我得到了这两个库,我在其中一个项目中使用了第一个库,它运行顺利,没有任何内存问题。
这些库是ListView的水平实现,它根据屏幕上可见的视图为您回收项目。 Scrollview不适用于无限滚动视图。
更新:现在我们有来自Android的RecyclerView,它也支持水平滚动,它还强制使用 Viewholder 模式