ListView的优化
public class Adapter extends ArrayAdapter<Fruit> {
private int resource = 0;
public Adapter(@NonNull Context context, int resource, @NonNull List<Fruit> objects) {
super(context, resource, objects);
this.resource = resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit = getItem(position);
View view = LayoutInflater.from(getContext()).inflate(resource, parent, false);
AppCompatImageView fruitImage = view.findViewById(R.id.fruit_image);
AppCompatTextView fruitName = view.findViewById(R.id.fruit_name);
fruitImage.setImageResource(fruit.getImageId());
fruitName.setText(fruit.getName());
return view;
}
}
在getView方法中每次都要把布局加载一遍,当ListView快速滚动的时候,会造成性能的瓶颈。方法中的convertView参数用于将之前加载的布局进行缓存,修改代码如下:
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit = getItem(position);
View view ;
if (convertView == null){
view = LayoutInflater.from(getContext()).inflate(resource, parent, false);
}else {
view = convertView;
}
AppCompatImageView fruitImage = view.findViewById(R.id.fruit_image);
AppCompatTextView fruitName = view.findViewById(R.id.fruit_name);
fruitImage.setImageResource(fruit.getImageId());
fruitName.setText(fruit.getName());
return view;
}
现在虽然不会重复加载布局,但是还是会调用View的FindViewById()方法来获取一次控件的实例。可以借助ViewHolder 进行优化
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit = getItem(position);
View view ;
ViewHolder viewHolder;
if (convertView == null){
view = LayoutInflater.from(getContext()).inflate(resource, parent, false);
viewHolder = new ViewHolder();
viewHolder.fruitImage = view.findViewById(R.id.fruit_image);
viewHolder.fruitName = view.findViewById(R.id.fruit_name);
view.setTag(viewHolder);
}else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.fruitImage.setImageResource(fruit.getImageId());
viewHolder.fruitName.setText(fruit.getName());
return view;
}
class ViewHolder{
AppCompatImageView fruitImage;
AppCompatTextView fruitName;
}
内部类ViewHolder用于对控件的实例进行缓存,当convertView为null时,创建ViewHolder对象,并将控件的实例都存放在ViewHolder中,调用View 的setTag()方法将ViewHolder对象存储在View中,当convertView不为null时,通过View的getTag()方法取出ViewHolder,这样所有控件的实例都存储在了ViewHolder中,就没必要每次都通过findViewById()方法来获取控件实例了。