1. 程式人生 > >介面卡模式 對 BaseAdapter 抽取封裝,減少程式碼冗餘。

介面卡模式 對 BaseAdapter 抽取封裝,減少程式碼冗餘。

 BaseAdapter 介面卡,是我們經常使用的。可能一個專案中都有十幾甚至幾十個。細心的同學可能會發現,每一個介面卡的結構基本相同,這就讓我們想到了程式碼抽取。

 BaseAdater 本身使用的就是介面卡模式。相信大家對這種模式都很瞭解,所以今天就使用介面卡模式對BaseAdapter 的程式碼進行抽取封裝。接下來會對比普通寫法和封裝完之後的寫法:

首先:通常的寫法

ListView 的 item.xml 佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:padding="10dp"
        android:text="姓名"
        android:id="@+id/item_name_tv"
        android:layout_width="match_parent"
        android:layout_height="40dp" />

</LinearLayout>
ListView 的介面卡:MyAdapter.class
public class MyAdapter extends BaseAdapter {
	private Context mContext;
	private List<String> mList;

	public MyAdapter(Context mContext,List<String> mList) {
		this.mContext=mContext;
		this.mList=mList;
	}

	@Override
	public int getCount() {
		return mList != null ? mList.size() : 0;
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return mList != null ? mList.get(position) : null;
	}

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

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder=null;
		if(convertView==null){
			convertView=LayoutInflater.from(mContext).inflate(R.layout.item, parent,false);
			holder=new ViewHolder(convertView);
			convertView.setTag(holder);
		}else{
			holder=(ViewHolder)convertView.getTag();
		}
		holder.nameTv.setText("姓名:"+mList.get(position));
		return convertView;
	}
	
	private class ViewHolder{
		private TextView nameTv;
		public ViewHolder(View view) {
			if(view==null)
				return;
			nameTv=(TextView)view.findViewById(R.id.item_name_tv);
		}
	}
}
資料展示:

public class MainActivity extends Activity {
	private ListView mListView;
	private List<String> mList=new ArrayList<String>();
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mListView=(ListView)findViewById(R.id.listview);
		getData();
		MyAdapter adapter=new MyAdapter(this, mList);
		mListView.setAdapter(adapter);
	}
	//獲取資料
	private void getData() {
		for (int i = 0; i < 10; i++) {
			mList.add("小明:"+i);
		}
	}
}
效果:


這是常用的寫法。但是介面卡多了你會發現

@Override
 public int getCount() {}

@Override
 public Object getItem(int position) { }

@Override
 public long getItemId(int position) {}

@Override
 public View getView(int position, View convertView, ViewGroup parent) {
}

這幾個方法一直在不斷的重複編寫,這樣寫我是看不下去的。所以封裝之路刻不容緩。

但是:要對試用多有的Adapter 需要解決以下問題

 1、資料物件基本都不相同,不能寫死

 2、展示的View 佈局基本不相同,不能寫死

所以,這裡就需要使用泛型


上程式碼:

AbsBaseAdapter.class

 T 物件泛型 ; H ViewHolder 泛型

public abstract class AbsBaseAdapter<T,H extends AbsBaseAdapter.IViewHolder> extends BaseAdapter {
	public Context mContext;
	public List<T> mList;
	private LayoutInflater mInflater;
	private int layoutId;// 佈局id
	public AbsBaseAdapter(Context mContext,int layoutId) {
		this.mContext = mContext;
		this.layoutId=layoutId;
		mInflater = LayoutInflater.from(mContext);
		mList=new ArrayList<T>();
	}

    /**
     * 設定資料
     * */
    public boolean addElements(List<T> mList) {
        if (this.mList != null)
            return this.mList.addAll(mList);
        else
            return false;
    }

	@Override
	public int getCount() {
		return mList != null ? mList.size() : 0;
	}

	@Override
	public T getItem(int position) {
		return mList != null ? mList.get(position) : null;
	}

	@Override
	public long getItemId(int position) {
		return position;
	}
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		H holder = null;
		if (convertView == null) {
			convertView = mInflater.inflate(layoutId, parent, false);
			holder = createViewHolder(convertView);
			convertView.setTag(holder);
		} else {
			holder = (H) convertView.getTag();
		}
		
		convertView(mList.get(position), position, holder);
		return convertView;
	}
	// 建立ViewHoler
	public abstract H createViewHolder(View view); 
	// 給佈局設定資料
	public abstract void convertView(T bean,int position,H holder);
	
	//所有 ViewHolder 都需要實現該介面
	public interface IViewHolder{
	}
}

然後讓 MyAdapter 繼承 AbsBaseAdapter 。

在看MyAdapter的程式碼    MyAdapter.class

public class MyAdapter extends AbsBaseAdapter<String, MyAdapter.ViewHolder> {
	
	public MyAdapter(Context mContext) {
		super(mContext, R.layout.item);
	}

	@Override
	public ViewHolder createViewHolder(View view) {
		return new ViewHolder(view);
	}
	
	@Override
	public void convertView(String bean, int position, ViewHolder holder) {
		holder.nameTv.setText("姓名:"+bean);
	}
	
	class ViewHolder implements AbsBaseAdapter.IViewHolder{
		private TextView nameTv;
		public ViewHolder(View view) {
			if(view==null)
				return;
			nameTv=(TextView)view.findViewById(R.id.item_name_tv);
		}
	}


}
是不是非常的簡潔,清晰!!!

然後 在Activity 中使用:

public class MainActivity extends Activity {
	private ListView mListView;
	private List<String> mList=new ArrayList<String>();
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mListView=(ListView)findViewById(R.id.listview);
		getData();
		MyAdapter adapter=new MyAdapter(this);
		adapter.addElements(mList);
		mListView.setAdapter(adapter);
	}
	//獲取資料
	private void getData() {
		for (int i = 0; i < 10; i++) {
			mList.add("小明:"+i);
		}
	}
}
到這裡 就大功告成。

以後再寫Adapter 時,可以直接繼承AbsAdapter 這個類。

你還可以在AbsAdapter 中繼續擴充套件一些可能用到的方法。例如

/**
	 * 新增單個數據
	 */
	public boolean addElement(T bean) {
		if (mList != null)
			return mList.add(bean);
		else
			return false;
	}

	/**
	 * 新增資料到指定位置
	 */
	public void addElement(int position, T bean) {
		if (mList != null)
			mList.add(position, bean);
	}

	/**
	 * 根據position新增資料
	 */
	public boolean addElements(int position, List<T> mList) {
		if (this.mList != null)
			return this.mList.addAll(position, mList);
		else
			return false;
	}

	/**
	 * 根據postion 刪除資料
	 */
	public T removeElement(int position) {
		if (mList != null)
			return mList.remove(position);
		else
			return null;
	}

	/**
	 * 刪除
	 */
	public boolean removeElement(T bean) {
		if (mList != null)
			return mList.remove(bean);
		else
			return false;
	}