使用adapter对ListView,GridView等进行适配时,要重写它的getView()方法。
下面是一个简单的示例,从本博客的上一篇文章Android launcher应用的简单实现粘贴过来:
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
//这里没有用ViewHolder
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
View appView = inflater.inflate(R.layout.icon_layout, null);
ImageView iv = (ImageView) appView.findViewById(R.id.app_icon);
//设置图标适应方式和大小
iv.setScaleType(ImageView.ScaleType.FIT_CENTER);
iv.setLayoutParams(new LinearLayout.LayoutParams(70, 70));
TextView tv = (TextView) appView.findViewById(R.id.app_name);
ResolveInfo info = apps.get(i);
//显示app图标
iv.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
//显示app名
String appName = info.loadLabel(getPackageManager()).toString();
tv.setText(appName);
return appView;
}
}
要显示多少数据,getView就会执行多少次。而按这种实现,每次都会创建一个view,是效率很低的做法。
下面稍稍改下:
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (null == view) {
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
view = inflater.inflate(R.layout.icon_layout, null);
}
ImageView iv = (ImageView) view.findViewById(R.id.app_icon);
//设置图标适应方式和大小
iv.setScaleType(ImageView.ScaleType.FIT_CENTER);
iv.setLayoutParams(new LinearLayout.LayoutParams(70, 70));
TextView tv = (TextView) view.findViewById(R.id.app_name);
ResolveInfo info = apps.get(i);
//显示app图标
iv.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
//显示app名
String appName = info.loadLabel(getPackageManager()).toString();
tv.setText(appName);
return view;
}
上面进行修改之后,不会每次都重新创建view了,而是view为null时才创建,效率有所提升。但这并不是最好的优化。下面看看用ViewHolder进行优化:
先在adapter的外面定义一个类ViewHolder:
static class ViewHolder{
ImageView img;
TextView tv;
}
然后对adapter的getView()方法进行如下修改:
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder;
if (null == view) {
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
view = inflater.inflate(R.layout.icon_layout, null);
holder = new ViewHolder();
holder.img = (ImageView) view.findViewById(R.id.app_icon);
holder.tv = (TextView) view.findViewById(R.id.app_name);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
//设置图标适应方式和大小
holder.img.setScaleType(ImageView.ScaleType.FIT_CENTER);
holder.img.setLayoutParams(new LinearLayout.LayoutParams(70, 70));
ResolveInfo info = apps.get(i);
//显示app图标
holder.img.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
//显示app名
String appName = info.loadLabel(getPackageManager()).toString();
holder.tv.setText(appName);
return view;
}
这样修改之后,避免每次调用getView()的时候都调用findViewById(),因此更进一步提升了性能,因为findViewById()也是耗费性能的操作。
另外需要说明下,ViewHolder这个名字换成别的自定义名也行,但是ViewHolder这个名字是官方推荐的,而且大家都这样写,所以最好约定俗成地保持这种习惯。