Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android:ListView緩存機制及BaseAdapter的三重境界(逗比式,普通式,文藝式)

android:ListView緩存機制及BaseAdapter的三重境界(逗比式,普通式,文藝式)

編輯:關於Android編程

大家都知道listview的格式是一定的 而數據源確是多重多樣的 這時候 就需要一種適配器來把數據源轉換成listview要顯示的格式

baseAdapter就誕生了。

\

listview和gridView的顯示和緩存機制 如下圖

\

大家都知道屏幕的大小是有限的 可是listview中的數據卻可能很多 所以手機不能一下子展示所有的數據 它只會加載屏幕上顯示的數據 。

如上圖,當我們把屏幕往下滑動時 item1回收到recycler 而item8要顯示在屏幕上 item8從recycler取出這樣一個布局文件 並重新設置好item8要顯示的數據 並設置要要顯示的位置。總之一句話 需要才顯示 顯示完就被回收到緩存。

至於題目為何說BaseAdapter的三重境界(逗比式,普通式,文藝式) 區別在哪裡那?就在如何運用listview的顯示和緩存機制

在listview的適配器上 有這樣一個方法

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		return null;
	}

其中逗比式 普通式 文藝式的區別就在於如何使用這個方法

下面我們通過一個實例 來比較adapter的三重境界孰強孰弱

要實現的效果如下

\

activity_main.xml

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
    <listview android:id="@+id/lv_listView" android:layout_width="match_parent" android:layout_height="match_parent"></listview>

</linearlayout>

item.xml
<!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%2D%2D%3E-->
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">

    <imageview android:id="@+id/iv_image" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignparentleft="true" android:src="@drawable/ic_launcher">

    <textview android:id="@+id/tv_nickName" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_torightof="@id/iv_image" android:gravity="center_horizontal" android:textsize="20sp" android:text="昵稱">

    <textview android:id="@+id/tv_content" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_torightof="@id/iv_image" android:layout_below="@id/tv_nickName" android:textsize="15sp" android:text="內容">

</textview></textview></imageview></relativelayout>

為了方便 ,我創建了一個myObject對象 用來封裝item.xml要顯示的數據

MyObject.class

package com.example.baseadapter;

import android.widget.ImageView;
import android.widget.TextView;

public class MyObject {
	private int imageViewId;
	private String nickName;
	private String content;

	public MyObject(int imageViewId, String nickName, String content) {
		this.imageViewId = imageViewId;
		this.nickName = nickName;
		this.content = content;
	}

	public String getNickName() {
		return nickName;
	}

	public String getContent() {
		return content;
	}

	public int getImageViewId() {
		return imageViewId;
	}

}

MainActivity.class
package com.example.baseadapter;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.ListView;

public class MainActivity extends Activity {
	private List list=new ArrayList();
	private ListView listView;
	private MyAdapter myAdapter;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		listView=(ListView) findViewById(R.id.lv_listView);
		for(int i=0;i<50;i++){
			list.add(new MyObject(R.drawable.ic_launcher, "昵稱"+i,	"內容"+i));
		}
		myAdapter=new MyAdapter(list, this);
		listView.setAdapter(myAdapter);
	}
}

自定義的adapter

MyAdapter.class

package com.example.baseadapter;

import java.util.List;

import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyAdapter extends BaseAdapter {

	private long sum = 0;
	private List list;
	private Context context;

	public MyAdapter(List list, Context context) {
		this.list = list;
		this.context = context;
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return list.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return list.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		// 逗比式
		 long star = System.nanoTime();
		 View view=View.inflate(context, R.layout.item, null);
		 ImageView imageView =(ImageView) view.findViewById(R.id.iv_image);
		 TextView nickName=(TextView) view.findViewById(R.id.tv_nickName);
		 TextView content=(TextView) view.findViewById(R.id.tv_content);
		 MyObject myObject=list.get(position);
		 imageView.setBackgroundResource(myObject.getImageViewId());
		 nickName.setText(myObject.getNickName());
		 content.setText(myObject.getContent());
		 long end = System.nanoTime();
		 sum += end - star;
		 Log.d("main", "逗比式" + sum);
		 return view;
		// 普通式
//		long star = System.nanoTime();//獲取系統納秒時間
//		if (convertView == null) {
//			convertView = View.inflate(context, R.layout.item, null);
//		}
//		ImageView imageView = (ImageView) convertView
//				.findViewById(R.id.iv_image);
//		TextView nickName = (TextView) convertView
//				.findViewById(R.id.tv_nickName);
//		TextView content = (TextView) convertView.findViewById(R.id.tv_content);
//		MyObject myObject = list.get(position);
//		imageView.setBackgroundResource(myObject.getImageViewId());
//		nickName.setText(myObject.getNickName());
//		content.setText(myObject.getContent());
//		long end = System.nanoTime();
//		sum += end - star;
//		Log.d("main", "普通式" + sum);
//		return convertView;
		// 文藝式
		// long star = System.nanoTime();
		// ViewHolder viewHolder;
		// if (convertView == null) {
		// viewHolder=new ViewHolder();
		// convertView = View.inflate(context, R.layout.item, null);
		// viewHolder.imageView = (ImageView) convertView
		// .findViewById(R.id.iv_image);
		// viewHolder.nickName = (TextView) convertView
		// .findViewById(R.id.tv_nickName);
		// viewHolder.content = (TextView) convertView
		// .findViewById(R.id.tv_content);
		// //通過setTag方式 使viewHolder和convertView綁定在一起
		// convertView.setTag(viewHolder);
		// }
		// viewHolder=(ViewHolder) convertView.getTag();
		// MyObject myObject = list.get(position);
		// viewHolder.imageView.setBackgroundResource(myObject.getImageViewId());
		// viewHolder.nickName.setText(myObject.getNickName());
		// viewHolder.content.setText(myObject.getContent());
		// long end = System.nanoTime();
		// sum += end - star;
		// Log.d("main", "文藝式"+sum);
		// return convertView;
	}

	// 避免重復的findViewById
	class ViewHolder {
		public ImageView imageView;
		private TextView nickName;
		private TextView content;
	}

}

BaseAdapter的三重境界(逗比式,普通式,文藝式)的代碼已經在上面

下面我們分析一下第一種為什麼叫逗比式

前面已經說了,liseview具有緩存機制 可以將使用過的item放入緩沖池中,而在這裡 每次調用getview方法的時候 我們都是創建新的view對象 並沒有利用listview的緩存機制

沒有任何處理 ,效率及其低下,所以我們稱它為逗比式

而第二種 普通式是利用了getview方法中傳入的contentview對象 並且加一個if判斷

		if (convertView == null) {
			convertView = View.inflate(context, R.layout.item, null);
		}
雖然只是一個if判斷 但是通過這個判斷 可以避免創建大量的contentview對象 節省了大量的時間 利用了ListView的緩存特性 如果沒有緩存才創建新的view 對getview方法進行了非常好的優化 但這僅僅只算入門,因為findViewById依然會浪費大量的時間 所以我們稱這種方法為普通式

那麼第三種境界 文藝式 就是對findViewById的優化了 把findViewById 也放入if判斷語句中 就ok了

我們需要創建一個內部類 裡面有三個成員變量 都是我們item.xml文件中的三個控件

	class ViewHolder {
		public ImageView imageView;
		private TextView nickName;
		private TextView content;
	}
通過viewHolder.setTag()方法 把viewHolder和contentView關聯在一起 然後通過getTag方法得到viewHolder

這種方法不僅利用了listview的緩存,更通過viewHolder來實現顯示視圖的緩存,避免多次使用findViewById方法

作為一個有情懷的程序員 這才是最文藝的寫法~

大家可能看到了我代碼中輸出的log日志 下面我附上結果 大家比較一下 這裡listview中只有50條數據 全部是滑倒底部

\\\

至此BaseAdapter的三重境界(逗比式,普通式,文藝式)孰強孰弱 一目了然~(如果有出入 請你把listview中的數據設置多一些)

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved