1. 程式人生 > >Android設計模式之策略模式

Android設計模式之策略模式

策略模式的定義:

策略模式定義了一系列演算法,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化。

策略模式的使用場景:

1.針對同一型別問題的多種處理方式,僅僅是具體行為有差別時。

2.需要安全封裝多種同一型別的操作時。

3.出現同一抽象類有多個子類,而又需要使用if-else或者switch-case來選擇具體的子類時。

策略模式UML圖

Android原始碼中的策略模式的實現

時間插值器(TimeInterpolator)

時間插值器的作用:根據時間流逝的百分比來計算當前屬性值改變的百分比。系統預置的有:線性插值器(LinearInterpolator),用於勻速動畫;加速減速插值器(AccelerateDecelerateInterpolator)用於起始時動畫加速,結尾時動畫減速;減速插值器(DecelerateInterpolator)用於隨著時間的推移動畫越來越慢,即減速動畫。這些插值器是策略模型的典型應用。

(型別估值器)TypeEvaluator

它的作用是根據當前屬性改變的百分比來計算改變後的屬性值,也就說TypeEvaluator計算得到的才是屬性的值。

時間插值器計算得到當前時間點的時間流逝百分比,TypeEvaluator根據這個百分比、屬性起始值、目標值來計算出當前時刻該屬性的值,最後這個值被設定給View,不斷重複這個過程就形成了動畫。系統預置的有整型屬性(IntEvaluator)、浮點型屬性(FloatEvaluator)、Color屬性(ArgbEvaluato)。

/**
 * Start the specified animation now.
 *
 * @param animation the animation to start now
 */
public void startAnimation(Animation animation) {
     //1.初始化動畫開始時間
    animation.setStartTime(Animation.START_ON_FIRST_FRAME);
     //2.對View設定動畫
    setAnimation(animation);
     //3.重新整理父類快取
    invalidateParentCaches();
   //4.重新整理View本身以及子View
    invalidate(true);
}

startAnimation中首先設定了動畫的起始時間,然後將該動畫設定到該View中,最後再向ViewGroup請求重新整理檢視,隨後ViewGroup就會呼叫dispatchDraw方法對這個View所在的區域進行重繪。對於某一個View的重繪最終呼叫ViewGroup中的drawChild(Canvas canvas,View child,long drawingtime)方法。

#View
 /**
     * This is where the invalidate() work actually happens. A full invalidate()
     * causes the drawing cache to be invalidated, but this function can be
     * called with invalidateCache set to false to skip that invalidation step
     * for cases that do not need it (for example, a component that remains at
     * the same dimensions with the same content).
     *
     * @param invalidateCache Whether the drawing cache for this view should be
     *            invalidated as well. This is usually true for a full
     *            invalidate, but may be set to false if the View's contents or
     *            dimensions have not changed.
     * @hide
     */
    public void invalidate(boolean invalidateCache) {
        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
    }

   #View
    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
            boolean fullInvalidate) {
... ...
    }

   #ViewGroup
   @Override
    protected void dispatchDraw(Canvas canvas) {
.....
drawChild(canvas, child, drawingTime)
     }

   #ViewGroup
    /**
     * Draw one child of this View Group. This method is responsible for getting
     * the canvas in the right state. This includes clipping, translating so
     * that the child's scrolled origin is at 0, 0, and applying any animation
     * transformations.
     *
     * @param canvas The canvas on which to draw the child
     * @param child Who to draw
     * @param drawingTime The time at which draw is occurring
     * @return True if an invalidate() was issued
     */
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        return child.draw(canvas, this, drawingTime);
    }

drawChild方法只是進行了一個轉發,所以要看下View的draw(Canvas canvas, ViewGroup parent, long drawingTime)是如何呼叫Animation的。