标签:
一、作用还是以Usb接口和Phone手机类的产品举例子,假设设计的Phone类中有 call(), sms(), takeAlong()属性方法,而在设计Usb接口时定义了 store(), takeAlong()的行为。如果现在有新的业务需求,需要生成 Xiaomi手机类具有 Phone类和Usb接口两者功能,假设Phone类和Usb接口已经在业务上投入使用,很显然,去修改原类中的方法和接口的行为去满足现在的新业务需求是不可取的,那么现在适配者模式就派上用场了。
适配器模式主要有两种:类适配模式和对象适配模式
1.类适配模式
大致的意思是新的业务类Xiaomi通过继承旧业务的类Phone并实现接口Usb来满足新的业务的一种适配方式。
代码如下:
Usb接口类
public interface Usb{ public void store(); public void takeAlong(); }Phone 类
public class Phone { public void call(){ System.out.print("phone can call"); } public void sms(){ System.out.print("phone can send messages"); } public void takeAlong() { System.out.println("Phone takeAlong"); } }适配后的Xiaomi类
public class Xiaomi extends Phone implements Usb{ public void store() { System.out.println("store implements usb"); } }适配完成后 就可以使用xiaomi 类去完成一些功能
Xiaomi xm = new Xiaomi(); xm.takeAlong(); xm.store(); xm.call();2.对象适配模式
实现的方式很简单,其实就是在适配的时候通过构造函数将旧的业务Phone 当作新的适配类(XiaomiWrapper)一个成员对象去处理,然后适配类只需要实现接口 Usb即可。
public class XiaomiWrapper implements Usb{ /** * 1.创建一个Wrapper类,持有原类的一个实例, * 2.在Wrapper类的方法中,调用实例的方法就行 */ private Phone phone; public XiaomiWrapper(Phone phone) { this.phone = phone; } @Override public void store() { } @Override public void takeAlong() { phone.takeAlong(); } }适配完后通过构造函数将原对象传入即可。
XiaomiWrapper xiaomiWrapper = new XiaomiWrapper(new Phone()); xiaomiWrapper.store(); xiaomiWrapper.takeAlong();Android 源码中的适配器模式的很好运用就是listView 中使用Adapter来显示数据。
// 代码省略 ListView myListView = (ListView)findViewById(listview_id); // 设置适配器 myListView.setAdapter(new MyAdapter(context, myDatas));
适配器类 // 适配器 public class MyAdapter extends BaseAdapter{ private LayoutInflater mInflater; List<String> mDatas ; public MyAdapter(Context context, List<String> datas){ this.mInflater = LayoutInflater.from(context); mDatas = datas ; } @Override public int getCount() { return mDatas.size(); } @Override public String getItem(int pos) { return mDatas.get(pos); } @Override public long getItemId(int pos) { return pos; } // 解析、设置、缓存convertView以及相关内容 @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; // Item View的复用 if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.my_listview_item, null); // 获取title holder.title = (TextView)convertView.findViewById(R.id.title); convertView.setTag(holder); } else { holder = (ViewHolder)convertView.getTag(); } holder.title.setText(mDatas.get(position)); return convertView; } }那么ListView是如何通过Adapter模式 ( 不止Adapter模式 )来运作的呢 ?
ListView继承自AbsListView,Adapter定义在AbsListView中,我们看一看这个类。
public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher, ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener, ViewTreeObserver.OnTouchModeChangeListener, RemoteViewsAdapter.RemoteAdapterConnectionCallback { ListAdapter mAdapter ; // 关联到Window时调用的函数 @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); // 代码省略 // 给适配器注册一个观察者,该模式下一篇介绍。 if (mAdapter != null && mDataSetObserver == null) { mDataSetObserver = new AdapterDataSetObserver(); mAdapter.registerDataSetObserver(mDataSetObserver); // Data may have changed while we were detached. Refresh. mDataChanged = true; mOldItemCount = mItemCount // 获取Item的数量,调用的是mAdapter的getCount方法 mItemCount = mAdapter.getCount(); } mIsAttached = true; } /** * 子类需要覆写layoutChildren()函数来布局child view,也就是Item View */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mInLayout = true; if (changed) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { getChildAt(i).forceLayout(); } mRecycler.markChildrenDirty(); } if (mFastScroller != null && mItemCount != mOldItemCount) { mFastScroller.onItemCountChanged(mOldItemCount, mItemCount); } // 布局Child View layoutChildren(); mInLayout = false; mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR; } // 获取一个Item View View obtainView(int position, boolean[] isScrap) { isScrap[0] = false; View scrapView; // 从缓存的Item View中获取,ListView的复用机制就在这里 scrapView = mRecycler.getScrapView(position); View child; if (scrapView != null) { // 代码省略 child = mAdapter.getView(position, scrapView, this); // 代码省略 } else { child = mAdapter.getView(position, null, this); // 代码省略 } return child; } }AbsListView定义了集合视图的框架,比如Adapter模式的应用、复用Item View的逻辑、布局Item View的逻辑等。子类只需要覆写特定的方法即可实现集合视图的功能,例如ListView。
ListView中的相关方法。
protected void layoutChildren() { // 代码省略 try { super.layoutChildren(); invalidate(); // 代码省略 // 根据布局模式来布局Item View switch (mLayoutMode) { case LAYOUT_SET_SELECTION: if (newSel != null) { sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom); } else { sel = fillFromMiddle(childrenTop, childrenBottom); } break; case LAYOUT_SYNC: sel = fillSpecific(mSyncPosition, mSpecificTop); break; case LAYOUT_FORCE_BOTTOM: sel = fillUp(mItemCount - 1, childrenBottom); adjustViewsUpOrDown(); break; case LAYOUT_FORCE_TOP: mFirstPosition = 0; sel = fillFromTop(childrenTop); adjustViewsUpOrDown(); break; case LAYOUT_SPECIFIC: sel = fillSpecific(reconcileSelectedPosition(), mSpecificTop); break; case LAYOUT_MOVE_SELECTION: sel = moveSelection(oldSel, newSel, delta, childrenTop, childrenBottom); break; default: // 代码省略 break; } } // 从上到下填充Item View [ 只是其中一种填充方式 ] private View fillDown(int pos, int nextTop) { View selectedView = null; int end = (mBottom - mTop); if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { end -= mListPadding.bottom; } while (nextTop < end && pos < mItemCount) { // is this the selected item? boolean selected = pos == mSelectedPosition; View child = makeAndAddView(pos, nextTop, true, mListPadding.left, selected); nextTop = child.getBottom() + mDividerHeight; if (selected) { selectedView = child; } pos++; } return selectedView; } // 添加Item View private View makeAndAddView(int position, int y, boolean flow, int childrenLeft, boolean selected) { View child; // 代码省略 // Make a new view for this position, or convert an unused view if possible child = obtainView(position, mIsScrap); // This needs to be positioned and measured setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]); return child; }ListView覆写了AbsListView中的layoutChilden函数,在该函数中根据布局模式来布局Item View。Item View的个数、样式都通过Adapter对应的方法来获取,获取个数、Item View之后,将这些Item View布局到ListView对应的坐标上,再加上Item View的复用机制,整个ListView就基本运转起来了。
* 更好的扩展性
在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
本文参考:http://www.codeceo.com/article/android-listview-adapter-2.html
标签:
原文地址:http://blog.csdn.net/mr_dv_bkhm/article/details/51351977