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的。