我有一个带有AbsListView的ListFragment,我写了一个ListAdapter:
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_item, container, false);
AbsListView mListView = (AbsListView) view.findViewById(R.id.list);
mListView.setAdapter(getAdapter(inflater));
mListView.setOnItemClickListener(this);
return view;
}
private ListAdapter getAdapter(final LayoutInflater inflater) {
return new ListAdapter() {
@Override
public boolean areAllItemsEnabled() {
return true;
}
@Override
public boolean isEnabled(int position) {
return true;
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_view_template, parent, false);
holder = new ViewHolder();
holder.itemImg = (ImageView) convertView.findViewById(R.id.img_item);
holder.itemTv = (TextView) convertView.findViewById(R.id.tv_item_name);
holder.opTv = (TextView) convertView.findViewById(R.id.tv_item_op);
holder.itemTv.setText(list.get(position).getName());
convertView.setTag(holder);
}
return convertView;
}
@Override
public int getItemViewType(int position) {
return 1;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public boolean isEmpty() {
return false;
}
};
}
当我逐步调试时,list
有14个项目,但getView
方法只被调用了7次(7个项目完全填满了我的屏幕)。当我向上滑动AbsListView时,getView
被再次调用了2次,前5个项目再次消失。
例如,我的list
有{0,1,2,3,4,5,6,7,8,9,10,11,12,13},结果是:
0
1
2
3
4
5
6(Items below here only disappear after sliding AbsListView up)
7
8
0
1
2
3
4
答案 0 :(得分:1)
这是因为convertView。 convertView是一个通过滚动列表创建和回收的视图。此视图可以减少GC调用并为您节省内存。滚动列表后,它首先由您最早的列表项分配,例如列表中的第一项消失,您看到第15项第一项的convertView再次传递给您。在这个时间它不是null,所以你跳过赋值给它并且它保留了作为第一项赋值的最后一个赋值的引用。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_view_template, parent, false);
holder = new ViewHolder();
holder.itemImg = (ImageView) convertView.findViewById(R.id.img_item);
holder.itemTv = (TextView) convertView.findViewById(R.id.tv_item_name);
holder.opTv = (TextView) convertView.findViewById(R.id.tv_item_op);
holder.itemTv.setText(list.get(position).getName());
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
// here you must use holder.opTv to change values for example initialize to new one
// here you must use holder.itemTv to change values for example initialize to new one
// .....
return convertView;
}
答案 1 :(得分:1)
您的getView
方法不是很好。请参阅此示例:http://www.vogella.com/tutorials/AndroidListView/article.html#adapterperformance_example
看起来应该类似于:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.item_view_template, null);
ViewHolder holder = new ViewHolder();
holder.itemImg = (ImageView) convertView.findViewById(R.id.img_item);
holder.itemTv = (TextView) convertView.findViewById(R.id.tv_item_name);
holder.opTv = (TextView) convertView.findViewById(R.id.tv_item_op);
convertView.setTag(holder);
}
ViewHolder holder = convertView.getTag();
holder.itemTv.setText(list.get(position).getName());
return convertView;
}
答案 2 :(得分:0)
我修改getView
方法:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
convertView = inflater.inflate(R.layout.item_view_template, parent, false);
holder = new ViewHolder();
holder.itemImg = (ImageView) convertView.findViewById(R.id.img_item);
holder.itemTv = (TextView) convertView.findViewById(R.id.tv_item_name);
holder.opTv = (TextView) convertView.findViewById(R.id.tv_item_op);
holder.itemTv.setText(list.get(position).getName());
convertView.setTag(holder);
return convertView;
}
只需删除if (convertView == null)
现在效果很好。谁可以解释一下?
答案 3 :(得分:0)
当我逐步调试它时,列表中有14个项目,但getView方法只调用了7次(7个项目完全填满了我的屏幕)。
适配器正在实例化新的View
以填充屏幕。之后,如果您只有一种类型View
来显示您的对象数组,那么Android会重复使用这些View
来优化流程(为您的每个对象创建新视图的代价很高)数组)。
在创建了7 View
之后,您就不会更新它(只有在convertView
为空时才会更新,例如在前7个getView(...)
调用中。
解决方案应该是:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_view_template, parent, false);
holder = new ViewHolder();
holder.itemImg = (ImageView) convertView.findViewById(R.id.img_item);
holder.itemTv = (TextView) convertView.findViewById(R.id.tv_item_name);
holder.opTv = (TextView) convertView.findViewById(R.id.tv_item_op);
convertView.setTag(holder);
} else {
holder = (ViewHolderItem) convertView.getTag();
}
holder.itemTv.setText(list.get(position).getName());
return convertView;
}
答案 4 :(得分:0)
这应该有效:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_view_template, parent, false);
holder = new ViewHolder();
holder.itemImg = (ImageView) convertView.findViewById(R.id.img_item);
holder.itemTv = (TextView) convertView.findViewById(R.id.tv_item_name);
holder.opTv = (TextView) convertView.findViewById(R.id.tv_item_op);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
holder.itemTv.setText(list.get(position).getName());
return convertView;
}