Android 自定义 BaseAdapter
我们在 Android 自定义 Adapter 中自定义了一个 YetAdapter
的适配器,用了好几次,都感觉不错,但那是数据量比较少的情况下,如果数据量一多,就特别卡顿,有时候会导致卡死,是什么原因造成的呢?
是因为 getView()
方法,界面上有多少列就会调用多少次 getView()
,每次都是新 inflate 一个 View,都要进行这个 XML 的解析,这样会
很浪费资源
所以我们要对 YetAdapter
进行优化,有两个目标
- 复用
convertView
- 用
ViewHolder
重用组件,不用每次都 `findViewById()
复用 ConvertView
因为界面上有多少个 Item,就要调用 getView()
多少次
我们先来看看之前的方法是什么样的?
@Override public View getView(int position, View convertView, ViewGroup parent) { convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item,parent,false); ImageView img_icon = (ImageView) convertView.findViewById(R.id.icon); TextView txt_aName = (TextView) convertView.findViewById(R.id.name); TextView txt_aDesc = (TextView) convertView.findViewById(R.id.desc); img_icon.setBackgroundResource(mData.get(position).getaIcon()); txt_aName.setText(mData.get(position).getaName()); txt_aDesc.setText(mData.get(position).getaDesc()); return convertView; }
从代码里可以看出,inflate()
每次都要加载一次 xml
其实这个 convertView
是系统提供给我们的可供服用的 View
,既然可复用,那么只要做一下判断就好
@Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView == null){ convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item,parent,false); } ImageView img_icon = (ImageView) convertView.findViewById(R.id.icon); TextView txt_aName = (TextView) convertView.findViewById(R.id.name); TextView txt_aDesc = (TextView) convertView.findViewById(R.id.desc); img_icon.setBackgroundResource(mData.get(position).getaIcon()); txt_aName.setText(mData.get(position).getaName()); txt_aDesc.setText(mData.get(position).getaDesc()); return convertView; }
ViewHolder 重用组件
上面的优化只做到了 XML 文件只加载一次,但 convertView.findViewById
还是调用了多次
其实我们的 ListView
中的每一项都是一模一样的布局,能否只调用一次就好?
答案是肯定的,但需要自己定义一个 ViewHolder
类来对这一部分进行性能优化
ViewHolder
其实就是一个静态类
static class ViewHolder{ ImageView img_icon; TextView txt_aName; TextView txt_aSpeak; }
然后修改 getView()
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){ convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item,parent,false); holder = new ViewHolder(); ImageView img_icon = (ImageView) convertView.findViewById(R.id.icon); TextView txt_aName = (TextView) convertView.findViewById(R.id.name); TextView txt_aDesc = (TextView) convertView.findViewById(R.id.desc); convertView.setTag(holder); //将Holder存储到convertView中 }else{ holder = (ViewHolder) convertView.getTag(); } img_icon.setBackgroundResource(mData.get(position).getaIcon()); txt_aName.setText(mData.get(position).getaName()); txt_aDesc.setText(mData.get(position).getaDesc()); return convertView; }
好了,完成后我们的 YetAdapter
就是这样了
package cn.twle.android.yetadapter; import android.content.Context; import android.widget.BaseAdapter; import android.widget.TextView; import android.widget.ImageView; import android.view.View; import android.view.ViewGroup; import android.view.LayoutInflater; import java.util.LinkedList; public class YetAdapter extends BaseAdapter { private LinkedList<YetLanguage> mData; private Context mContext; public YetAdapter(LinkedList<YetLanguage> mData, Context mContext) { this.mData = mData; this.mContext = mContext; } @Override public int getCount() { return mData.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){ convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item,parent,false); holder = new ViewHolder(); holder.img_icon = (ImageView) convertView.findViewById(R.id.icon); holder.txt_aName = (TextView) convertView.findViewById(R.id.name); holder.txt_aDesc = (TextView) convertView.findViewById(R.id.desc); 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_aDesc.setText(mData.get(position).getaDesc()); return convertView; } static class ViewHolder{ ImageView img_icon; TextView txt_aName; TextView txt_aDesc; } }
把 Android ListView 列表视图 最后一个范例中的 YetAdapter
替换一下,发现正常运行