建立一個可重複使用的自訂BaseAdapter
本節引言:
如題,本節帶給大家的是建構一個可重複使用的自訂BaseAdapter,我們每每涉及到ListView GridView等其他的Adapter控件,都需要自己另外寫一個BaseAdapter類,這樣顯得非常麻煩, 又例如,我們想在一個介面顯示兩個ListView的話,我們也是需要些兩個BaseAdapter... 這,程式設計師都是喜歡偷懶的哈,這節我們就來寫一個可重複使用的自訂BaseAdapter類別~
1.我們一點點開始改:
首先我們把上節寫的自訂BaseAdapter貼下,等下我們就要對他進行升級改造
* 由 Jay 創立於 2015 年 9 月 21 日 0021。 */
public 類別 MyAdapter 擴充 BaseAdapter{
私有 Context mContext;
私有 LinkedList; mData;
public MyAdapter() {
# }
public MyAdapter(LinkedList mData this. mContext = mContext;
}
@Override
public int getCount() {
@Override
public Object getItem(int position) {
return null;
}
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_list, parent, false);
holder = new ViewHolder());#. View.findViewById(R.id.img_icon);
holder.txt_content = (TextView) convertView.findViewById(R.id.txt_content);
con. holder = (ViewHolder) convertView.getTag();
}
holder.img_icon.setImageResource(mData.get(position).getImgId());
holder.txt_content.setText(mData.get(position).getContent());
return convertView;
}
##
if (mData == null) {
mData ) mData.add(data);
notifyDataSetChanged();
}
//往特定位置,新增一個元素
public void add(int position,Data data){
new LinkedList<>( );
}
mData.add(position, data);
data) {
if(mData ! = null) {
mData.remove(data);
}
void remove(int position) {
if(mData ! = null) {
mData.remove(position);
}
public void clear() {
if(mData != null ) {
mData.clear();
}
ViewHolder {
ImageView img_icon;
TextView txt_content;
}
}
#
升級1:將Entity設定成泛型
好的,畢竟我們傳遞過來的Entitiy實體類別可能千奇百怪,例如有Person,Book,Wether等,所以我們 將Entity設定成泛型,修改後的程式碼如下:
public 類別 MyAdapter<T> 擴充 BaseAdapter {
私有 Context mContext;
私有 LinkedList
public MyAdapter() {
# }
public MyAdapter(LinkedList
}
@Override
public int getCount() {
@Override
public Object getItem(int position) {
return null;
}
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_list, parent, false);
holder = new ViewHolder());#. View.findViewById(R.id.img_icon);
holder.txt_content = (TextView) convertView.findViewById(R.id.txt_content);
con. holder = (ViewHolder) convertView.getTag();
}
holder.img_icon.setImageResource(mData.get(position).getImgId());
holder.txt_content.setText(mData.get(position).getContent());
return convertView;
}
##
if (mData == null) {
mData ) mData.add(data);
notifyDataSetChanged();
}
//往特定位置,新增一個元素
public void add(int position,T data){
new LinkedList<>( );
}
mData.add(position, data);
data) {
if(mData ! = null) {
mData.remove(data);
}
void remove(int position) {
if(mData ! = null) {
mData.remove(position);
}
public void clear() {
if(mData != null ) {
mData.clear();
}
ViewHolder {
ImageView img_icon;
TextView txt_content;
}
}
#
好的,上面我們做的事只是將Data類型換成了泛型T!
升級2:ViewHolder類別的升級改造:
我們先來看看前面我們的ViewHolder做了什麼? 答:findViewById,設定控制項狀態; 下面我們要在完成這個基礎上,將getView()方法大部分的邏輯寫到ViewHolder類別裡, 這個ViewHolder要做的事:
- 定義一個尋找控制項的方法,我們的想法是透過揭露公共的方法,當呼叫方法時傳遞過來 控制項id,以及設定的內容,例如TextView設定文字: public ViewHolder setText(int id, CharSequence text){文字設定}
- 將convertView重複使用部分搬到這裡,那就需要傳遞一個context物件了,我們把需要取得 的部分都寫到構造方法中!
- 寫一堆設定方法(public),例如設定文字大小顏色,圖片背景等!
好的,接下來我們就來一步步改造我們的ViewHolder類別
1)相關參數與建構方法:
private SparseArray<View> mViews; //儲存ListView 的 //存放convertView
# private int position; ///遊標
private Context context; //Context上下文
/建構法outRes) {
mViews = new SparseArray< >();
this.context = context;
View convertView = Lay View.setTag(this);
item = convertView;
}
# ImageView img_icon;
TextView txt_content;
#}
TextView txt_content;
#}
2)綁定ViewHolder與Item
在上面的基礎上我們再加入一個綁定的方法
public static ViewHolder bind(Context context, View convertView, ViewGroup parent,
{
ViewHolder holder;
if(convertView == null) {
holder context, parent, layoutRes);
} else {
holder = (ViewHolder) convert
holder.position = position;
return holder;
}
public <T extends View> T getView( int id) {
mViews .put(id, t);
}
return t;
}
#
4) 接下來我們再定義一個公開出來的方法
* 取得目前條目
*/
public View getItemView() {
return item;
}
/**
* 取得條目位置
*/
public int getItemPosition() {
返回位置;
}
/**
* 設定文字
*/
public ViewHolder setText(int id, CharSequence text) {
View view = getView(id);
if(view instanceof TextView) . # }
返回此;
}
/**
* 設定圖片
*/
public ViewHolder setImageResource(int id, int drawableRes) {
;
if(view instanceof ImageView) {
((ImageView) view).setImageResource(drawableRes );#c drawableRes);
}
return this;
}
#/**
* 設定點選監聽
*/
public ViewHolder setOnClickListener(int id, View.OnClickListenerlistener) {
getView(id).setOnClickListener (listener ) );
回傳此;
}
/**
* 設定可見
*/
public ViewHolder setVisibility(int id, int visible) {
getView(id).setVisibility (可見);
返回此;
}
/**
* 設定標籤
*/
public ViewHolder setTag(int id, Object obj) {
getView(id). setTag (obj);
return this;
}
#//其他方法可自行擴展
好的,ViewHolder的改造升級完成~
升級3:定義一個抽象方法,完成ViewHolder與Data資料集的綁定
public abstract void bindView(ViewHolder holder, T obj);
我們建立新的BaseAdapter的時候,實作這個方法就好,另外,別忘了把我們自訂 的BaseAdapter改成abstact抽象的!
升級4:修改getView()部分的內容
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.bind(parent.getContext(), convertView, parent, mLayoutRes , position); bindView(holder,getItem(position)); return holder.getItemView(); }
#2.升級完畢,我們寫程式碼來體驗下:
我們要實現的效果圖:
就是上面有兩個列表,佈局不一樣,但我只使用一個BaseAdapter類別來完成上述效果!
關鍵程式碼如下:
MainActivity.java:
#私有Context mContext;
私有ListView list_book;
私有ListView list_app;## myAdapter1 = null;
private MyAdapter
私有清單
私人清單<圖書>; mData2 = null;
@Override
protected void onCreate(Bundle savedInstanceState) {## ); setContentView(R.layout.activity_main);
mContext = MainActivity.this;
init();
}
private void init( );
list_app = (ListView) findViewById(R.id.list_app);
/ mData1.add(new App( R.mipmap.iv_icon_baidu,"百度"));
mData1.add(new App(R.mipmap.iv_icon_douban,"豆瓣"));
. "支付寶"));
mData2 = new ArrayList
mData2.add(new Android("《第一行程式碼郭氏》","閔 mData2.add(new Android("《第一行程式碼郭氏》","閔 mData2.add(new Android("《第一行程式碼郭葉》","閔 mData2.add(new Android("《第一行程式碼郭》","閔 mData2.add(new Android("《第一行程式碼郭》","閩號" ## mData2.add(new Book("《Android群英傳》","徐宜生"));
mData2.add(new Book("《Android工作藝術》」,"任玉剛探索》","任玉剛探索」,"。
## //適配器初始化
myAdapter1 = new MyAdapter
# holder.setImageRe holder.setText(R.id.txt_aname,obj.getaName()) ;
}
# };
my), @Override
public void bindView(ViewHolder holder,書籍物件) {
holder.setText(R.id.txt_bname,obj.getbName());
}
# } ;
//ListView設定下Adapter:
list_book.setAdapter(myAdapter2);
# }
我們寫的可重複使用的BaseAdapter的使用就如上面所述~
3.程式碼範例下載:
ListViewDemo4.zip
貼下最後寫好的MyAdapter類別吧,可以依照自己的需求擴充:
MyAdapter.java:
* 由 Jay 創立於 2015 年 9 月 22 日 0022。 */
公共抽象類別MyAdapter
私有 ArrayList
private int mLayoutRes; // 佈局id
public MyAdapter() {
}
public MyAdapter(ArrayList
this.mData = mData;
this.mLayoutRes = mLayoutRes;
}
## @Override
? mData.size() : 0;
}
# @Override
public T getItem(int position) ## @Override
public long getItemId(int position) {
return position;# position, View convertView, ViewGroup parent) {
ViewHolder holder = ViewHolder.bind(parent.getContext(), convertView, parent, mLayoutRes
bindView(holder, getItem(position));
return holder.getItemView() ;
}
public abstract public abstract void bindView(ViewHolder holder, T obj) -c## ## if ( mData == null) {
mData = new ArrayList<>();
notifyDataSetChanged();
}
//往特定位置,新增一個元素
public void add(int position, T data) {
mData = new ArrayList<> ;();
}
mData.add(position, data);
data) {
if ( mData != null) {
mData.remove(data);
}# public void remove(int position) {
if ( mData != null) {
mData.remove(position);
) public void clear() {
# if (mData ! = null) {
mData.clear();
}
static 類 ViewHolder {
private SparseArray< ;查看> mViews; // 儲存ListView的item中的View
private View item; // 蹲convertView
private int position; //遊標
private Context context; //情境情境
//建構方法,完成相關初始化
private ViewHolder(Context context, ViewGroupparent, intlayoutRes) {
mViews = new SparseArray View convertView = LayoutInflater.from(context).inflate( layoutRes, parent, false);
con. //綁定ViewHolder與item
public static ViewHolder bind(Context context, View convertView, ViewGroup parent,
int layoutRes, int position) {
ViewHolderholder;
if (convertView == null) {
holder = new ViewHolder(context, parent, layoutRes);
} else {
holder = (ViewHolder) convertView.getTag(();
0;> }
holder.position =地點;
}
@SuppressWarnings("unchecked")
public
T t = (T) mViews.get(id);
if (t == null) {
t = (T) item.findViewById }
return t;
## /**
* 以取得目前條目
*/
public View getItemView() {
/**
* 取得條目位置
*/
public int getItemPosition() {
返回位置;
public ViewHolder setText(int id, CharSequence text) {
以檢視view = getView(id);
if (view instanceof TextView) {
}
所回復中;
}
# }
# /**
* 設定文字
*/
public ViewHolder setImageResource(int id, int drawableView;##view if (view instanceof ImageView) {
((ImageView) view).setIm view.setBackgroundResource(drawableRes);
# }
/**
* 設定點選監聽
*/
# /**
* 設定可見
*/
public getView(id).setOnClickListener(listener);
返回此;
}
{
getView(id).setVisibility(visible);
return this;
}
# j) {
getView(id).setTag(obj);
return this;
}
# //使用其他方法與其他方法111
#o##
本節小結:
本節為大家介紹如何來實現一個可供復用的BaseAdapter,當然大家可以在這個的基礎上根據 自己的需求進行修改,例如透過非同步設定網路圖片等~改程式碼是參考鴻洋大神的影片寫的: 影片連結:Android-打造萬用適配器另外,實際編寫遇到一些問題,非常感謝Berial(B神)的耐心點撥~ありがとうございます~