參考: http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html
工作原理: 1.ListView針對List中每個item,要求Adapter給其一個視圖(getView) 2.一個新的視圖被傳回并顯示
如果我們有上億個item要顯示怎麼辦?為每個項目建立一個新視圖?NO!這不可能~~~Android實際上提供了緩存視圖
Android中有個叫做Recycler(反複循環器)的構件,下圖是它的工作原理:
1.如果你有10億個項目(item),其中隻有可見的項目存在記憶體中,其他的在Recycler中 2.ListView先請求一個type1視圖(getView),然後請求其他可見的項目。conVertView在getView中是null的。 3.當item1滾出螢幕,并且一個新的項目從螢幕底部滑上來時,ListView再請求一個type1視圖。 convertView此時不是空值了,它的值是item1.你隻需要設定新的資料傳回convertView, 不必重新建立一個視圖。這樣直接使用convertView進而減少了不必要的view的建立。
!更快的方式是定義一個ViewHolder,将convertView的tag設定為ViewHolder,當convertView不為空時 重新使用ViewHolder。
ViewHolder隻是将需要緩存的子view封裝好,convertView的setTag方法才是将這些緩存起來供下次調用。 當你的listview裡布局多樣化的時候 viewholder的作用就有比較明顯的展現了。 當然了,單一模式的布局一樣有性能優化的作用隻是不直覺。 假如你2種模式的布局當發生回收的時候,你會用setTag分别記錄是哪兩種, 這兩種模式會被封裝到viewholder中進行儲存友善你下次使用。 VH就是個靜态類,與緩存無關的。
public class MultipleItemsList extends ListActivity {
private MyCustomAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCustomAdapter();
for (int i = 0; i < 50; i++) {
mAdapter.addItem("item " + i);
}
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter {
private ArrayList mData = new ArrayList();
private LayoutInflater mInflater;
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
@Override
public int getCount() {
return mData.size();
}
@Override
public String getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, >View</strong> convertView, ViewGroup parent) {
System.out.println("getView " + position + " " + convertView);
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item1, null);
holder = new ViewHolder();
holder.textView = (TextView)convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
}
參考資料:
http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html
http://www.eoeandroid.com/thread-72369-1-1.html
http://www.cnblogs.com/felix-hua/archive/2012/01/06/2314436.html
http://blog.csdn.net/jacman/article/details/7087995
http://fatkun.com/2012/01/android-viewholder.html