轉載請注明出處:http://blog.csdn.net/zhaokaiqiang1992
現在大家都知道用ViewHolder來實作listview的優化了,但是,ViewHolder到底要用什麼來修飾呢?這種修飾有什麼意義呢?在一個ListView裡面,存在多少個VIewHolder執行個體呢?為什麼VIewHolder能夠減少findview的次數,優化效率呢?為了弄清楚這個問題,我做了以下測試,測試代碼很簡單,就是下面這些
public class MainActivity extends Activity {
public static int itemId = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView listView = new ListView(this);
listView.setAdapter(new MyAdapter());
setContentView(listView);
}
private class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
return 50;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.item,
parent, false);
viewHolder = new ViewHolder();
viewHolder.tv = (TextView) convertView.findViewById(R.id.tv);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.tv.setText("item" + position);
Log.d("TAG", "position=" + position + "---" + viewHolder.toString());
return convertView;
}
}
private class ViewHolder {
// private static class ViewHolder {
// private final class ViewHolder {
// private static final class ViewHolder {
private int id;
public ViewHolder() {
id = itemId;
Log.d("TAG", "ViewHolder" + id);
itemId++;
}
TextView tv;
@Override
public String toString() {
return "--------id=" + id;
}
}
}
我簡單說一下代碼是什麼意思,ViewHolder有一個成員變量id,在toString()使用,用來區分不同的ViewHolder,在構造函數中,對id進行指派,itemId是一個靜态變量,每初始化一次就+1,我們可以根據構造函數的列印次數,來計算ViewHolder的執行個體化次數,根據toString()可以來判斷到底是使用了哪一個ViewHolder。getVIew中的寫法是固定的,下面是測試結果:
private class ViewHolder修飾,界面内可見的item數量是9個,ViewHolder初始化了10次,之後開始複用ViewHolder。

private static class ViewHolder修飾,界面内可見的item數量是9個,ViewHolder初始化了10次,之後開始複用ViewHolder。
private final class ViewHolder修飾,界面内可見的item數量是9個,ViewHolder初始化了10次,之後開始複用ViewHolder。
private static final class ViewHolder修飾,完全一樣!
其實一上來我就貼一張圖就ok了,因為這幾種完全一樣,不管用什麼修飾,ViewHolder都會初始化目前界面可見item的數量+1次,和convertView的執行個體化次數是一樣的,是以,我麼不管使用什麼修飾都是沒問題的,也是沒必要的。
static修飾類,在這裡是靜态内部類,并不是說隻存在一個執行個體,而是可以通路外部類的靜态變量,final修飾類則是不讓該類繼承,我們這裡使用final毫無根據,是以,以後寫ViewHolder的時候,可以不糾結了,加什麼加啊,什麼都不用加!
----------------------------------------------------------------------------------------
今天又請教了公司一個大神,他的回答如下:
這篇文章中沒有提到加載時機的問題吧。在我的了解中:靜态内部類主要作用就是,内部類是否需要隔離“外部類的this對象(指針)”。内部類是有 this 指針的,可以“直接”通路外部類的 成員變量和成員函數(包括私有的成員)。而靜态内部類,沒有這個this指針,是以無法“直接”調用。
個人的習慣,我通常會把内部靜态類,作為一個單獨的java檔案。
但是Android代碼中,卻經常使用的Builder,LayoutParams都是以靜态内部類的方式存在啊。我們可以根據實際使用情況來效仿。
另外還要提一點,内部靜态類(特别是私有内部靜态類),在代碼混淆上效果更好。會增加反編譯的難度。
-------------------------------------------------------
對于這篇文章,我了解。ViewHolder的構造和複用,與靜不靜态沒關。核心是ListView(AdapterView),通過getView(int position, View convertView, ViewGroup parent) 的convertView會為開發者傳入一個可以複用的對象。開發者需要利用該對象,減少應用記憶體的消耗。
如果從減少記憶體消耗的角度來開。我認為ViewHolder還是應該修飾成static比較好。這樣ViewHolder中可以減少MainActivity的this指針,由于減少了一個this指針的引用,也會對MainActivity的引用計數大大減少。MainActivity的this指針繼承于android的Context上下文,對于Context的回收遺漏,是Android記憶體管理中很大的問題。我們減少了對Context的引用,可以更容易減少Context引用計數出現問題。