引言:在长期的android教学中,不难发现ListView是一个让学生十分头痛的组件,原因很简单,这里有个适配器的概念,对于学生来讲是一个从未涉及的新的领域,那么我们就通过这边文章来初识一下软件设计模式中的适配器模式。
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.
将一个类的接口变成客户端所期待的另一中接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
其中用到适配器模式的经典例子就是插座匹配问题,直接给图:
2.适配器模式的分类:
适配器模式主要分为两种:类适配器和对象适配器
如上图所示(截取自《Head First Design Patterns》一书),主要包括三个部分:
1) Target目标角色。该角色定义把其他类转换为我们的期待接口。
2) Adaptee源角色。就是原始的类和接口对象,它是已经存在的,只是不符合现有的要求,而需要利用适配器角色的包装。
3) Adapter适配器角色。适配器模式的核心角色,其它两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单;把源角色转换为目标角色;通过继承或是组合的方式。
3.适配器模式的优势:
1)适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定它们。
2)增加了类的通透性,我们访问的Target目标角色,但是具体的实现都委托给了源角色,而这些对高层次模块是透明的,也是它不需要关心得。
3)调高了类的复用性和灵活性非常好。如果觉得适配器不够好,只要修改适配器就行,其它的代码都不用修改,适配器就是一个灵活的构件,想用就用。
4.适配器模式在android源码中的应用:
在Android源码中,ListView中用到的就是适配器模式。ListView用于显示列表数据,但列表数据形式多种多样(),为了处理和显示不同的数据,我们需要对应的适配器作为桥梁。
在ListView中有一个变量ListAdapter mAdapter;是显示在view试图上的数据:
/**
* The adapter containing the data to be displayed by this view
*/
ListAdapter mAdapter;
在ListAdapter中定义了所需要的接口函数:
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)等接口函数。
此时的ListAdapter就是一个Target目标角色,而我们的ListView就是一个Client。因此为了适配和显示一些数据,如Cursor等,所以就需要相应的适配器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;
}
// 实现ListAdapter目标接口的getCount函数,通过返回源角色mCursor的方法getCount函数
/**
* @see android.widget.ListAdapter#getCount()
*/
public int getCount() {
if (mDataValid && mCursor != null) {
return mCursor.getCount();
} else {
return 0;
}
}
// 实现ListAdapter目标接口的getItem函数,通过返回源角色mCursor的方法moveToPosition函数
/**
* @see android.widget.ListAdapter#getItem(int)
*/
public Object getItem(int position) {
if (mDataValid && mCursor != null) {
mCursor.moveToPosition(position);
return mCursor;
} else {
return null;
}
}
// 实现ListAdapter目标接口的getItemId函数,通过返回源角色mCursor的方法getLong函数
/**
* @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类型接口通过CursorAdapter适配器转换成目标角色ListAdapter目标接口,继而让ListView使用,并展示。
以上就是android中关于ListView的适配器模式使用一些简单分享,希望对大家学习ListView有所帮助。