android: ListView歷次優化,androidlistview
第一版:
ListView一屏顯示多少對象其內部就創建多少View對象。滑動時退出的緩存對象留給滑進去時調用getView傳的convertView。因為如果每次都findViewById查找創建視圖對象,浪費性能和內存。所以我們都利用布局創建View給convertView。布局內部的view對象都事先通過findViewById查找好存到某一個集合對象-ViewHolder:視圖持有者上。並把這個ViewHolder對象放到convertView的Tag上,通過getView返回給Adapter。下一屏時這個緩存的View對象就會被傳進來,此時convertView的Tag屬性中有包含了ViewHoler對象-convertView布局內部的對象。這樣我們直接用ViewHoler中的對象進行處理了。
下面就是這個版本通用使用方法:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHoler holer;
if (convertView == null) {
//convertView = View.inflate(mActivity, R.layout.list_**, null);
holer = new ViewHoler();
holer.iv_New_Image = (ImageView) convertView.findViewById(R.id.iv_New_Image);
holer.tv_Content = (TextView) convertView.findViewById(R.id.tv_Content);
holer.tv_Date = (TextView) convertView.findViewById(R.id.tv_Date);
convertView.setTag(holer);
} else {
holer = (ViewHoler) convertView.getTag();
}
//自行填寫完整
return convertView;
}
class ViewHoler {
public ImageView iv_New_Image;
public TextView tv_Content;
public TextView tv_Date;
}
View Code
因為本人懶惰,所以這種findViewById太麻煩了,所以我自己寫了個工具。根據自動生成代碼。 自定生成ViewHoler代碼(當前頁面只播放一次,再次查看ctrl+f5一下)。工具下載鏈接:http://pan.baidu.com/s/1i4tXwvr
第二個版本:
該版本只是對第一個版本上的設計上的改變,將與ViewHoler相關的代碼集中到了ViewHoler身上。getView職責更加明確,邏輯也更加清晰。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHoler holer;
if (convertView == null) {
//convertView = View.inflate(mActivity, R.layout.list_**, null);
holer = new ViewHoler();
} else {
holer = (ViewHoler) convertView.getTag();
}
//自行填寫完整
return convertView;
}
class ViewHoler {
public ImageView iv_New_Image;
public TextView tv_Content;
public TextView tv_Date;
public ViewHoler(View convertView){
this.iv_New_Image = (ImageView) convertView.findViewById(R.id.iv_New_Image);
this.tv_Content = (TextView) convertView.findViewById(R.id.tv_Content);
this.tv_Date = (TextView) convertView.findViewById(R.id.tv_Date);
convertView.setTag(this);
}
}
View Code
工具已經在這個版本上更新了 http://pan.baidu.com/s/1bnVNbPl
第三個版本:
這個版本與前面的版本本質不同,前面都是靜態代碼。這個ViewHoler中想根據資源Id來獲取View。而我們的View存在內部的一個HashMap中,因為HashMap對於查找的時間復雜度是O(1)的,並且因為是KeyValue不擔心重復。返回View類型改為泛型是的獲取對象時上層不需要強轉。
//用法
ViewHolerHelper helper=new ViewHolerHelper(convertView);
ImageView view=helper.getView(R.id.iv_New_Image);
public class ViewHolerHelper {
private HashMap<Integer,View> mViews;
View convertView;
public ViewHolerHelper(View convertView){
mViews=new HashMap<Integer, View>();
convertView.setTag(this);
this.convertView=convertView;
}
public <T> T getView(Integer R_Id){
View view=null;
if(!mViews.containsKey(R_Id)){
view=convertView.findViewById(R_Id);
if(view!=null){
mViews.put(R_Id, view);
}
}
else{
view=mViews.get(R_Id);
}
return (T)view;
}
}
View Code