摘要:基于Android應(yīng)用程序的開發(fā),系統(tǒng)界面不僅形式多樣,內(nèi)容上也越來越豐富,這些特點(diǎn)都得利于適配器的使用。BaseAdapter最大的特點(diǎn)是靈活而優(yōu)雅,開發(fā)人員可以輕松的構(gòu)造BaseAdapter并將其搭載到所需的控件中去,從而使系統(tǒng)呈現(xiàn)不同的效果。該文從BaseAdapter的構(gòu)造過程闡述了適配器的原理并通過程序?qū)崿F(xiàn)適配器搭載不同UI界面控件的過程。
關(guān)鍵詞:Android;BaseAdapter;適配器
中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2015)26-0085-03
Based on BaseAdapter Adapter to Understand in the Android
OU Chu-xiang
(Guangzhou Railway Polytechnic, Guangzhou 510430, China)
Abstract: Application development based-on Android not only presented in various forms, also enriched in its contents, all this can contributed to the use of an adapter. The most important feature of BsedAdapter is flexible and elegant, which can be easily constructed and implied to the needed controlers thus making a various appearing effect by the developers. The theory of construction of BaseAdapter and the programmed process of different UI interface controllers equipped with the adapter is proposed in this paper.
Key words: Android; BaseAdapter; the adapter
1 概述
在Android軟件開發(fā)學(xué)習(xí)中,適配器模式(Adapter Pattern)是必須學(xué)習(xí)的。GOF(Gang of four)的《Design Pattern》中設(shè)配器模式定義:把一個(gè)類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法再一起工作的兩個(gè)類能夠在一起工作[1]。理解這段定義,我們可以從手機(jī)充電方面去理解。手機(jī)充電器可以看作一個(gè)適配器,而220V交流電電源是一個(gè)類,手機(jī)是另一個(gè)類,手機(jī)需要的電壓是5.0V電壓,所以在充電時(shí)需要一個(gè)變壓器(充電器)將220V電壓轉(zhuǎn)換成手機(jī)所需的5.0V電壓,這正像是適配器所做的事。
BaseAdapter在Android引用程序中應(yīng)用非常廣泛,它是一個(gè)基礎(chǔ)數(shù)據(jù)適配器,其用途是將一組雜亂的數(shù)據(jù)按照一定的規(guī)則應(yīng)用到ListView、Spinner、Gallery和GridView等UI界面組件中。也就是說,Adapter可以看作數(shù)據(jù)源和UI界面組件之間數(shù)據(jù)溝通的橋梁,如圖1所示:
圖 1
2 對(duì)原生Adapter的理解
在開發(fā)過程中,程序員會(huì)經(jīng)常使用Adapter,因此谷歌公司給Android定義了一些原生的Adapter。這些原生的Adapter不僅負(fù)責(zé)提供數(shù)據(jù),而且還負(fù)責(zé)創(chuàng)建每一個(gè)條目的視圖,所以我們可以輕松的引用這些Adapter。原生的Adapter最有用、最常用的主要有以下兩個(gè):
1)ArrayAdapter類
ArrayAdapter類繼承了BaseAdapter類,利用JAVA泛型來定義綁定的數(shù)據(jù)類型對(duì)象,從而從數(shù)據(jù)類型對(duì)象的toString方法獲得相應(yīng)的值,用來創(chuàng)建和填充文本視圖。
2)SimpleCursorAdapter類
SimpleCursorAdapter類的基類同樣也是BaseAdapter類,它可以把一個(gè)布局中的視圖和(通常從Content Provider 查詢返回的)游標(biāo)的特定列綁定在一起[2]。
3 創(chuàng)建一個(gè)自己的適配器
既然前面講的ArrayAdapter類和SimpleCursorAdapter類的基類是BaseAdapter類,那么我們就可以依照這兩個(gè)類來編寫自己的Adapter。在繼承BaseAdapter類之后,我們需要實(shí)現(xiàn)getCount()、getItem()、getItemId()和getView()幾個(gè)方法。其中g(shù)etCount()返回列表項(xiàng)的長度;getItem()返回指定列表項(xiàng)數(shù)據(jù);getItemId()返回指定列表項(xiàng)在列表中的位置;getView()返回指定的列表視圖。具體代碼如下:
public class StructureAdapter extends BaseAdapter
{
//初始化數(shù)據(jù)
private List
private Context mContext;
private LayoutInflater mInflater;
public StructureAdapter(List
{
客服熱線:400-656-5456??客服專線:010-56265043??電子郵箱:longyuankf@126.com
電信與信息服務(wù)業(yè)務(wù)經(jīng)營許可證:京icp證060024號(hào)
Dragonsource.com Inc. All Rights Reserved
super();
this.mList = list;
this.mContext = context;
//獲取到當(dāng)前視圖壓力泵
mInflater = LayoutInflater.from(mContext);
}
@Override
public int getCount()
{
return mList.size();
}
@Override
public Object getItem(int position)
{
return mList.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
return mInflater.inflate(resource, null);
}
}
在這里,我們應(yīng)該重點(diǎn)去完成getView()的代碼實(shí)現(xiàn),在實(shí)現(xiàn)代碼前,還需要去創(chuàng)建一個(gè)XML的試圖文件和一個(gè)數(shù)據(jù)類型對(duì)象模型的Java文件,XML也就是代碼中resource。這里創(chuàng)建一個(gè)簡單的視圖文件Item.xml,視圖中有一個(gè)ImageView和兩個(gè)TextView,布局如圖2:
圖 2
數(shù)據(jù)類型對(duì)象模型的Java文件可以創(chuàng)建一個(gè)ItemModel.java文件,代碼如下:
public class ItemModel
{
public int ItemImageResId;
public String ItemTitle;
public String ItemContent;
public ItemModel (int itemImageResId, String itemTitle, String itemContent)
{
super();
ItemImageResId = itemImageResId;
ItemTitle = itemTitle;
ItemContent = itemContent;
}
}
1)簡單實(shí)現(xiàn)視圖代碼
在實(shí)現(xiàn)getView()里面代碼時(shí),我們不考慮其他情況的前提下,可以這樣實(shí)現(xiàn)代碼:
public View getView(int position, View convertView, ViewGroup parent)
{
View view = mInflater.inflate(R.layout.item, null);
ImageView imageView = (ImageView) view .findViewById(R.id.iv_image);
TextView title = (TextView)view.findViewById(R.id.tv_title);
TextView content = (TextView)view.findViewById(R.id.tv_content);
ItemModel model= mList.get(position);
imageView.setImageResource(model.ItemImageResId);
title.setText(model.ItemTitle);
content.setText(model.ItemContent);
return view;
}
這種實(shí)現(xiàn)方式可以清晰的表述出適配器所綁定的視圖,利于初學(xué)者理解Adapter原理。但這種方式也有其弊端,因?yàn)樗鼪]有充分考慮到Android所運(yùn)行的性能環(huán)境,Android所運(yùn)行的環(huán)境中硬件資源是有限的,像上述代碼在運(yùn)行時(shí)會(huì)重復(fù)創(chuàng)建視圖資源,消耗大量的內(nèi)存資源。因此,我們必須優(yōu)化代碼,減少資源的消耗。其實(shí)在Android中有一個(gè)Recycler構(gòu)
建,可以幫助優(yōu)化代碼。我們結(jié)合getView()方法來看Recycler的工作原理[3],如圖3:
圖3
從圖3中可以看出,Recycler構(gòu)建就是在滑動(dòng)屏幕后,當(dāng)Item1滑動(dòng)出屏幕,將其重新構(gòu)建視圖及賦值產(chǎn)生出Item8,達(dá)到重復(fù)利用的效果,減少硬件資源的消耗。
2)優(yōu)化視圖實(shí)現(xiàn)代碼
public View getView(int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
//view未被實(shí)例化,緩存池中沒有view的緩存,所以需要新建
convertView = mInflater.inflate(R.layout.item, null);
}
ImageView imageView = (ImageView) convertView .findViewById(R.id.iv_image);
TextView title = (TextView)convertView.findViewById(R.id.tv_title);
TextView content = (TextView)convertView.findViewById(R.id.tv_content);
ItemModel model= mList.get(position);
imageView.setImageResource(model.ItemImageResId);
title.setText(model.ItemTitle);
content.setText(model.ItemContent);
return convertView;
}
代碼實(shí)現(xiàn)雖然只多寫一段條件判斷代碼,但這段代碼才是整個(gè)getView()方法的核心。在條件判斷為真的時(shí)候,內(nèi)部去創(chuàng)建視圖,避免視圖的重復(fù)被創(chuàng)建。
以上代碼在Eclipse、Android SDK4.1環(huán)境下開發(fā),在SDK4.3、SDK5.1等調(diào)試通過。
4 結(jié)束語
設(shè)計(jì)Adapter時(shí)需要有代碼重構(gòu)的思想,這也符合面向?qū)ο蟪绦蛟O(shè)計(jì)思想,針對(duì)特有的接口設(shè)計(jì)Adapter可以解決數(shù)據(jù)與UI界面組件不匹配的情況。在設(shè)計(jì)時(shí)也需要考慮資源的消耗問題,優(yōu)化我們的Adapter。
參考文獻(xiàn):
[1] GOF. Design Patterns: Elements of Reusable Object-Oriented Software[M]. Pearson Education,2000:95-96.
[2] Reto Meier.Android 4 高級(jí)編程[M].3版.北京:清華大學(xué)出版社,2013:138.
[3] Satya Komatineni,Dave MacLean.精通Android[M]. 北京:人民郵電出版社,2013:127-131.