适配器模式

前言:

定义:适配器模式是把一个类的接口变换成客户端所期待的另一种接口,从而使得原本因接口不匹配而无法一起工作的两个类能协同工作。

适配器是将两个不兼容的类融合在一起,它有点像粘合剂,将不同的东西通过一个转换使得它们能够协作起来.


Android源码的适配器模式

1.首先看ListView的父类,AbsListView。

public abstract class AbsListView extends AdapterView implements TextWatcher,
        ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
        ViewTreeObserver.OnTouchModeChangeListener,
        RemoteViewsAdapter.RemoteAdapterConnectionCallback {
    ListAdapter mAdapter;
    
    /**
     * 关联到 Window时,通过 Adapter来获取 Item View 的数量、布局、数据等
     */
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        final ViewTreeObserver treeObserver = getViewTreeObserver();
        treeObserver.addOnTouchModeChangeListener(this);
        if (mTextFilterEnabled && mPopup != null && !mGlobalLayoutListenerAddedFilter) {
            treeObserver.addOnGlobalLayoutListener(this);
        }

        /**
         * 给设配器注册一个观察者
         */
        if (mAdapter != null && mDataSetObserver == null) {
            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);

            // Data may have changed while we were detached. Refresh.
            mDataChanged = true;
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();
        }
    }
    
    
    /**
     * Subclasses should NOT override this method but
     *  {@link #layoutChildren()} instead.
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);

        mInLayout = true;

        final int childCount = getChildCount();
        if (changed) {
            for (int i = 0; i < childCount; i++) {
                getChildAt(i).forceLayout();
            }
            mRecycler.markChildrenDirty();
        }

        //布局 Child View
        layoutChildren();
        mInLayout = false;

        mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;

        // TODO: Move somewhere sane. This doesn't belong in onLayout().
        if (mFastScroll != null) {
            mFastScroll.onItemCountChanged(getChildCount(), mItemCount);
        }
    }
}

AbsListView 定义了集合视图的逻辑框架,比如 Adapter模式的应用、复用 Item View 的逻辑、布局自视图的逻辑等。

2.ListView 覆写了的 layoutChildren。

ListView 覆写了 AbsListView 中的 layoutChildren。在 layoutChildren 中根据布局模式来布局 Item View,例如有从上而下,也有从下而上开始布局的(qq聊天的气泡布局,最新的消息到窗口的最底部)。我们来看看这两种实现

  1. 从上而下填充 Item View(只是其中的一种方式)
 /**
 * Fills the list from pos down to the end of the list view.
 *
 * @param pos The first position to put in the list
 *
 * @param nextTop The location where the top of the item associated with pos
 *        should be drawn
 *
 * @return The view that is currently selected, if it happens to be in the
 *         range that we draw.
 */
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++;
    }

    setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
    return selectedView;
}

总结:

ListView 等集合控件通过 Adapter来获取 Item View 的数量、布局、数据等,在这里尤为重要的就是 View类型的对象,也就是 Item View.由于它返回的是一个 View抽象,而千变万化的 UI视图都是 View 的子类,通过依赖抽象原则和 Adapter 模式就将 Item View 的变化隔离了,保证了 AbsListView 类族的高度可定制化。在获取到 View之后,将这些 View 通过特定的布局方式设置到对应的位置,再加上 Item View 的复用机制,整个 ListView就运转起来了。

深度拓展 RecyclerView

你可能感兴趣的:(适配器模式)