介面卡模式 對 BaseAdapter 抽取封裝,減少程式碼冗餘。
阿新 • • 發佈:2018-11-02
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;
}