天天看點

ViewHolder到底用什麼修飾?static?final?static final?



轉載請注明出處: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。

ViewHolder到底用什麼修飾?static?final?static final?

    private static class ViewHolder修飾,界面内可見的item數量是9個,ViewHolder初始化了10次,之後開始複用ViewHolder。

ViewHolder到底用什麼修飾?static?final?static final?

    private final class ViewHolder修飾,界面内可見的item數量是9個,ViewHolder初始化了10次,之後開始複用ViewHolder。

ViewHolder到底用什麼修飾?static?final?static final?

    private static final class ViewHolder修飾,完全一樣!

ViewHolder到底用什麼修飾?static?final?static final?

    其實一上來我就貼一張圖就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引用計數出現問題。