當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > 淺談android中的適配器模式
引言:在長(zhǎng)期的android教學(xué)中,不難發(fā)現(xiàn)ListView是一個(gè)讓學(xué)生十分頭痛的組件,原因很簡(jiǎn)單,這里有個(gè)適配器的概念,對(duì)于學(xué)生來(lái)講是一個(gè)從未涉及的新的領(lǐng)域,那么我們就通過(guò)這邊文章來(lái)初識(shí)一下軟件設(shè)計(jì)模式中的適配器模式。
1.適配器模式的定義:
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatile interfaces.
將一個(gè)類(lèi)的接口變成客戶端所期待的另一中接口,從而使原本因接口不匹配而無(wú)法在一起工作的兩個(gè)類(lèi)能夠在一起工作。
其中用到適配器模式的經(jīng)典例子就是插座匹配問(wèn)題,直接給圖:
2.適配器模式的分類(lèi):
適配器模式主要分為兩種:類(lèi)適配器和對(duì)象適配器
如上圖所示(截取自《Head First Design Patterns》一書(shū)),主要包括三個(gè)部分:
1) Target目標(biāo)角色。該角色定義把其他類(lèi)轉(zhuǎn)換為我們的期待接口。
2) Adaptee源角色。就是原始的類(lèi)和接口對(duì)象,它是已經(jīng)存在的,只是不符合現(xiàn)有的要求,而需要利用適配器角色的包裝。
3) Adapter適配器角色。適配器模式的核心角色,其它兩個(gè)角色都是已經(jīng)存在的角色,而適配器角色是需要新建立的,它的職責(zé)非常簡(jiǎn)單;把源角色轉(zhuǎn)換為目標(biāo)角色;通過(guò)繼承或是組合的方式。
3.適配器模式的優(yōu)勢(shì):
1)適配器模式可以讓兩個(gè)沒(méi)有任何關(guān)系的類(lèi)在一起運(yùn)行,只要適配器這個(gè)角色能夠搞定它們。
2)增加了類(lèi)的通透性,我們?cè)L問(wèn)的Target目標(biāo)角色,但是具體的實(shí)現(xiàn)都委托給了源角色,而這些對(duì)高層次模塊是透明的,也是它不需要關(guān)心得。
3)調(diào)高了類(lèi)的復(fù)用性和靈活性非常好。如果覺(jué)得適配器不夠好,只要修改適配器就行,其它的代碼都不用修改,適配器就是一個(gè)靈活的構(gòu)件,想用就用。
4.適配器模式在android源碼中的應(yīng)用:
在Android源碼中,ListView中用到的就是適配器模式。ListView用于顯示列表數(shù)據(jù),但列表數(shù)據(jù)形式多種多樣(),為了處理和顯示不同的數(shù)據(jù),我們需要對(duì)應(yīng)的適配器作為橋梁。
在ListView中有一個(gè)變量ListAdapter mAdapter;是顯示在view試圖上的數(shù)據(jù):
/**
* The adapter containing the data to be displayed by this view
*/
ListAdapter mAdapter;
在ListAdapter中定義了所需要的接口函數(shù):
package android.widget;
/**
* Extended {@link Adapter} that is the bridge between a {@link ListView}
* and the data that backs the list. Frequently that data comes from a Cursor,
* but that is not
* required. The ListView can display any data provided that it is wrapped in a
* ListAdapter.
*/public interface ListAdapter extends Adapter {
/**
* Indicates whether all the items in this adapter are enabled. If the
* value returned by this method changes over time, there is no guarantee
* it will take effect. If true, it means all items are selectable and
* clickable (there is no separator.)
*
* @return True if all items are enabled, false otherwise.
*
* @see #isEnabled(int)
*/
public boolean areAllItemsEnabled();
/**
* Returns true if the item at the specified position is not a separator.
* (A separator is a non-selectable, non-clickable item).
*
* The result is unspecified if position is invalid. An {@link ArrayIndexOutOfBoundsException}
* should be thrown in that case for fast failure.
*
* @param position Index of the item
*
* @return True if the item is not a separator
*
* @see #areAllItemsEnabled()
*/
boolean isEnabled(int position);
}
它是繼承自Adapter:
其中Adapter定義了getCount()、getItemViewType(int position)等接口函數(shù)。
此時(shí)的ListAdapter就是一個(gè)Target目標(biāo)角色,而我們的ListView就是一個(gè)Client。因此為了適配和顯示一些數(shù)據(jù),如Cursor等,所以就需要相應(yīng)的適配器CursorAdapter,代碼如下:
public abstract class CursorAdapter extends BaseAdapter implements Filterable,
CursorFilter.CursorFilterClient {。。。
protected Cursor mCursor;
protected ChangeObserver mChangeObserver;
protected DataSetObserver mDataSetObserver;
protected CursorFilter mCursorFilter;
。。。
/**
* Returns the cursor.
* @return the cursor.
*/
public Cursor getCursor() {
return mCursor;
}
// 實(shí)現(xiàn)ListAdapter目標(biāo)接口的getCount函數(shù),通過(guò)返回源角色mCursor的方法getCount函數(shù)
/**
* @see android.widget.ListAdapter#getCount()
*/
public int getCount() {
if (mDataValid && mCursor != null) {
return mCursor.getCount();
} else {
return 0;
}
}
// 實(shí)現(xiàn)ListAdapter目標(biāo)接口的getItem函數(shù),通過(guò)返回源角色mCursor的方法moveToPosition函數(shù)
/**
* @see android.widget.ListAdapter#getItem(int)
*/
public Object getItem(int position) {
if (mDataValid && mCursor != null) {
mCursor.moveToPosition(position);
return mCursor;
} else {
return null;
}
}
// 實(shí)現(xiàn)ListAdapter目標(biāo)接口的getItemId函數(shù),通過(guò)返回源角色mCursor的方法getLong函數(shù)
/**
* @see android.widget.ListAdapter#getItemId(int)
*/
public long getItemId(int position) {
if (mDataValid && mCursor != null) {
if (mCursor.moveToPosition(position)) {
return mCursor.getLong(mRowIDColumn);
} else {
return 0;
}
} else {
return 0;
}
}
@Override
public boolean hasStableIds() {
return true;
}
其中源角色Cursor接口如下所示:
public interface Cursor {
。。。
/**
* Returns the numbers of rows in the cursor.
*
* @return the number of rows in the cursor.
*/
int getCount();
/**
* Returns the current position of the cursor in the row set.
* The value is zero-based. When the row set is first returned the cursor
* will be at positon -1, which is before the first row. After the
* last row is returned another call to next() will leave the cursor past
* the last entry, at a position of count().
*
* @return the current cursor position.
*/
int getPosition();
。。。
/**
* Move the cursor to an absolute position. The valid
* range of values is -1 <= position <= count.
*
*
This method will return true if the request destination was reachable,
* otherwise, it returns false.
*
* @param position the zero-based position to move to.
* @return whether the requested move fully succeeded.
*/
boolean moveToPosition(int position);
。。。
/**
* Returns the value of the requested column as a long.
*
*
The result and whether this method throws an exception when the
* column value is null, the column type is not an integral type, or the
* integer value is outside the range [Long.MIN_VALUE
,
* Long.MAX_VALUE
] is implementation-defined.
*
* @param columnIndex the zero-based index of the target column.
* @return the value of that column as a long.
*/
long getLong(int columnIndex);
。。。
}
這就將Cursor類(lèi)型接口通過(guò)CursorAdapter適配器轉(zhuǎn)換成目標(biāo)角色ListAdapter目標(biāo)接口,繼而讓ListView使用,并展示。
以上就是android中關(guān)于ListView的適配器模式使用一些簡(jiǎn)單分享,希望對(duì)大家學(xué)習(xí)ListView有所幫助。