天天看點

【處女作】android中的ListView結合BaseAdapter執行個體 ,加入ViewHolder實作高性能ListView

基本上我的部落格是根據我手頭的項目來寫,如有不對的地方,希望大家能給樓主指出來,在此先道聲謝謝!

【處女作】android中的ListView結合BaseAdapter執行個體 ,加入ViewHolder實作高性能ListView

    android項目中需要制作一個類似于youtube的視訊清單的界面,可采用ListView的方式實作,listView實作最好的方法就是配合Adapter(擴充卡)為其添資料,當然直接在java代碼中為其添加資料也可以,但是不能實作動态資料的添加,比如說擷取web伺服器或者是其他程式中的資料。

關于Adapter:我們經常用"Men in the middle"中句話來描述它,也 就是“中間者”的意思。可以将它了解成資料和UI(View)之間的一個橋梁。

【處女作】android中的ListView結合BaseAdapter執行個體 ,加入ViewHolder實作高性能ListView

listview下的常用的adapter有:SimpleAdapter,ArrayAdapter,BaseAdapter等,其中我覺得最實用的就是BaseAdapter啦~

然後我們詳細講下這個。

BaseAdapter是個抽象類,繼承它需要實作的方法有:

getCount(), getItem(int position), 

getItemId(int position),

getView(int position, View convertView, ViewGroup parent)

首先通過代碼來簡單介紹下:

class MyImgAdapter extends BaseAdapter {

		@Override
		public int getCount() {
			// 根據他的傳回值得到 listView的長度
			return 0;
		}

		@Override
		public Object getItem(int position) {
			// 傳回目前Item顯示的資料,友善在Activity中的onItemClick方法中調用
			return null;
		}

		@Override
		public long getItemId(int position) {
			// 長按傳回目前Item顯示的資料,友善在Activity中的onItemClick方法中調用
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// position就是位置從0開始,convertView是ListView中每一項要顯示的view
			// 通常return 的view也就是convertView
			// parent就是父窗體了,也就是ListView了.
			return null;
		}
           

可能還有些小盆于看不明白,不要着急,看了下面的解釋你就明白了

【處女作】android中的ListView結合BaseAdapter執行個體 ,加入ViewHolder實作高性能ListView

ListView繪制的過程如下:

第一步:系統在繪制ListView之前,将會先調用getCount方法來擷取Item的個數。

第二步:開始繪制ListView清單,每繪制一個Item就會調用一次getView方法,在此方法内就可以引用事先定義好的xml來确定顯示的效果并傳回一個View對象作為一個Item顯示出來。也正是在這個過程中完成了擴充卡的主要轉換功能,把資料和資源以開發者想要的效果顯示出來,一行行繪制,直到行數超過getCount()的傳回值。

這兩個方法是自定ListView顯示效果中最為重要的,同時隻要重寫好了就兩個方法,ListView就能完全按開發者的要求顯示。而getItem和getItemId方法将會在調用ListView的響應方法的時候被調用到。是以要保證ListView的各個方法有效的話,這兩個方法也得重寫。比如:沒有完成getItemId方法的功能實作的話,當調用ListView的getItemIdAtPosition()方法時将會得不到想要的結果,因為該方法就是調用了對應的擴充卡的getItemId方法。

接下來我們來寫個簡單的demo來實作下:

為了保證代碼的高效性,以下的代碼用到了一些優化政策,客官老爺們可以放心的直接用到項目中啦!!不過在寫之前大家還需要了解下convertview和viewholder這兩個東東。

convertview:官方解釋是,The old view to reuse, if possible。原理上講就是當ListView滑動的過程中 會有item被滑出螢幕 而不再被使用 這時候Android會回收這個條目的view 這個view也就是這裡的convertView。

ViewHolder:

就是一個持有者的類,他裡面一般沒有方法,隻有屬性,作用就是一個臨時的儲存器,把你getView方法中每次傳回的View存起來,可以下次再用。這樣做的好處就是不必每次都到布局檔案中去拿到你的View,提高了效率。      

第一步:建立一個android項目,我的項目名字是BaseAdapterDemo

第二步:修改activity_main.xml檔案

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context=".MainActivity" >

   <ListView
        android:id="@+id/listview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

</RelativeLayout>
           

第三步:編寫ListView的xml檔案,這裡我隻添加了一個TextView,大家也可以加入其他東西。比如一個清單有可以點選的圖檔(ImageButton),相關資訊的TextView,以及一些Button。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context=".MainActivity" >

   <TextView
        android:id="@+id/textview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

</RelativeLayout>
           

第四步:編寫MainActivity.java代碼,在onCreate方法下面插入以下代碼

class MyAdapter extends BaseAdapter {
		Context mContext;// 用于接收傳遞過來的Context對象
		LayoutInflater inflater;

		public MyAdapter(Context context) {
			mContext = context;
			inflater = LayoutInflater.from(mContext);
		}

		@Override
		public int getCount() {
			// 這裡我就傳回8了,也就是一共有8項資料項
			return 8;
		}

		@Override
		public Object getItem(int position) {
			// 傳回目前Item顯示的資料,友善在Activity中的onItemClick方法中調用
			return position;
		}

		@Override
		public long getItemId(int position) {
			// 長按傳回目前Item顯示的資料,友善在Activity中的onItemClick方法中調用
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder viewHolder = null;
			if (convertView != null) {
				// 當item1被移除螢幕的時候,我們會重新new一個View給新顯示的item 而如果使用了這個convertView
				// 我們其實可以複用它,這樣就省去了new View的大量開銷
				convertView = inflater.inflate(R.layout.listitem1, parent, false);  
				viewHolder = new ViewHolder();  
				viewHolder.textView = (TextView)convertView.findViewById(R.id.textview);   
                convertView.setTag(viewHolder);  
                convertView.setTag(viewHolder);  
			} else {
				 // 沒有供複用的view 按一般的做法建立view
				viewHolder = (ViewHolder) convertView.getTag();  
			}
			 //配置每個list的資料
			convertView.textView.setText(Integer.toString(position));  
			return convertView;
		}
	}

	// 定義的ViewHolder,非常簡單,裡面隻有一個TextView
	class ViewHolder {
		TextView textView;
	}
           

第五步:運作項目就可以看到效果啦。

參考博文:

listview加載性能優化ViewHolder

利用convertView優化ListView性能

如果有問題歡迎郵件交流:我的郵箱[email protected]