Section Introduction:
In the previous section, we learned how to use a ListView and customize a simple BaseAdapter. From the code, we can see two important methods: getCount() and getView(). The getView method will be called as many times as there are items on the screen. At this point, you may notice a clue: each time a View is newly inflated, the XML has to be parsed, which wastes resources. Of course, a list of dozens or hundreds of items doesn't show any obvious problem, but what if there are more items or a more complex layout? Therefore, learning ListView optimization is very important. This section focuses on BaseAdapter optimization. There are two optimization points: reusing convertView and using ViewHolder to reuse components, so you don't have to call findViewById every time. Let's understand this through code!
1. Reuse ConvertView:
As mentioned above, how many Items there are on the screen, getView() will be called that many times! Let's look at the getView() code we wrote in the previous section:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list_animal,parent,false);
ImageView img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
TextView txt_aName = (TextView) convertView.findViewById(R.id.txt_aName);
TextView txt_aSpeak = (TextView) convertView.findViewById(R.id.txt_aSpeak);
img_icon.setBackgroundResource(mData.get(position).getaIcon());
txt_aName.setText(mData.get(position).getaName());
txt_aSpeak.setText(mData.get(position).getaSpeak());
return convertView;
}
Right, inflate() has to load the xml every time. In fact, this convertView is a cached View object provided by the system for us to reuse. So let's make a judgment and modify it. The optimized code is as follows:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list_animal,parent,false);
}
ImageView img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
TextView txt_aName = (TextView) convertView.findViewById(R.id.txt_aName);
TextView txt_aSpeak = (TextView) convertView.findViewById(R.id.txt_aSpeak);
img_icon.setBackgroundResource(mData.get(position).getaIcon());
txt_aName.setText(mData.get(position).getaName());
txt_aSpeak.setText(mData.get(position).getaSpeak());
return convertView;
}
2. Reusing Components with ViewHolder
Hehe, getView() will be called many times, so findViewById() naturally has to be called many times as well. Since the Items in our ListView generally have the same layout, we can optimize this further. We can define a ViewHolder class ourselves to improve performance! The modified code is as follows:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list_animal,parent,false);
holder = new ViewHolder();
holder.img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
holder.txt_aName = (TextView) convertView.findViewById(R.id.txt_aName);
holder.txt_aSpeak = (TextView) convertView.findViewById(R.id.txt_aSpeak);
convertView.setTag(holder); //将Holder存储到convertView中
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.img_icon.setBackgroundResource(mData.get(position).getaIcon());
holder.txt_aName.setText(mData.get(position).getaName());
holder.txt_aSpeak.setText(mData.get(position).getaSpeak());
return convertView;
}
static class ViewHolder{
ImageView img_icon;
TextView txt_aName;
TextView txt_aSpeak;
}
That's right, it's that simple. From now on, just write BaseAdapter following this template, haha. In addition, regarding the static modifier on ViewHolder: whether to define it as static has nothing to do with the number of objects inside. Adding static is so that when this Holder is used in multiple places, the class only needs to be loaded once. If it is used only once, it doesn't matter whether you add it or not! ——Berial (B God)'s original words~
Section Summary:
Alright, there are roughly two optimizations for BaseAdapter as mentioned above, very simple: reuse ConvertView and customize ViewHolder to reduce findViewById() calls~ If you have other suggestions for BaseAdapter optimization, feel free to propose them, thanks~