ValueAnimator基于Choreographer frame callback 通過(guò)判斷當(dāng)前時(shí)間缨硝,調(diào)用View相關(guān)屬性摩钙,刷新UI實(shí)現(xiàn)動(dòng)畫效果。
其中核心是AnimationHandler查辩。AnimationHandler胖笛, 是一個(gè)靜態(tài)單例Handler供所有的Animator調(diào)用,內(nèi)部基于Choreographer周期callback更新UI frame宜岛,使用ThreadLocal方式實(shí)現(xiàn)同步长踊。
其中AnimationFrameCallbackProvider抽象了封裝Choreographer的接口,用戶可以自實(shí)現(xiàn)基于其他形式的刷新接口谬返,因?yàn)镃horeographer是基于實(shí)際硬件的UI刷新機(jī)制接口之斯,自定義適用于非硬件形式的測(cè)試日杈。
postFrameCallback(Choreographer.FrameCallback callback)
postCommitCallback(Runnable runnable) {
而內(nèi)部類MyFrameCallbackProvider作為默認(rèn)封裝Choreographer處理動(dòng)畫的機(jī)制Provider接口
那如何實(shí)現(xiàn)動(dòng)畫的機(jī)制呢遣铝?答案是向Choreographer注冊(cè)FrameCallback ,每次到frameTime時(shí)執(zhí)行動(dòng)畫刷新UI,再注冊(cè)莉擒,當(dāng)前接口
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};
其中doAnimationFrame就是我們的動(dòng)畫執(zhí)行函數(shù)接口酿炸,那我們需要對(duì)上層動(dòng)畫抽象執(zhí)行動(dòng)畫的函數(shù)接口。doAnimationFrame處理所有實(shí)現(xiàn)AnimationFrameCallback 接口的doAnimationFrame()
interface AnimationFrameCallback {
boolean doAnimationFrame(long frameTime)
}
AnimationHandle維護(hù)frame callback隊(duì)列涨冀,
private final ArrayList<AnimationFrameCallback> mAnimationCallbacks =
new ArrayList<>();
AnimationHandler向上提供api
addAnimationFrameCallback
removeCallback
addAnimationFrameCallback提供注冊(cè)AnimationFrameCallback接口填硕,當(dāng)上層第一次向Provider注冊(cè)時(shí),添加默認(rèn)的mFrameCallback接口鹿鳖,觸發(fā)Choreographer callback機(jī)制扁眯。
removeCallback移除注冊(cè)AnimationFrameCallback接口
由上所知,我們?cè)倏碫alueAnimator恰恰實(shí)現(xiàn)了AnimationFrameCallback接口翅帜,內(nèi)部調(diào)用getAnimationHandler()姻檀,基于AnimationHandler實(shí)現(xiàn)動(dòng)畫機(jī)制。
我們看下ValueAnimator的簡(jiǎn)單使用方法:
ValueAnimator animator = ValueAnimator.ofInt(500);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
mView.setX(value);
}
});
animator.start();
發(fā)現(xiàn)主要做了兩步動(dòng)作:
1 配置動(dòng)畫參數(shù)
2 添加回調(diào)函數(shù)涝滴,收到值后執(zhí)行動(dòng)畫的具體實(shí)現(xiàn)绣版。
第二點(diǎn)我們可以猜測(cè)該回調(diào)必定在AnimationFrameCallback的doAnimationFrame中被執(zhí)行。
我們順藤摸瓜查看其邏輯歼疮,果然如此!
doAnimationFrame
animateBasedOnTime
animateValue
mUpdateListeners.get(i).onAnimationUpdate(this);
以上我們大致了解了ValueAnimator的整個(gè)動(dòng)畫實(shí)現(xiàn)機(jī)制杂抽,關(guān)于ProvertyValue,插值器, KeyFrame等的實(shí)現(xiàn)機(jī)制本文不再贅述韩脏。
源碼分析總計(jì):ValueAnimator很好的抽象了動(dòng)畫的邏輯機(jī)制缩麸,功能定義職責(zé)清晰,值得學(xué)習(xí)參考赡矢。
1 AnimationHandler封裝Choreographer的相關(guān)接口杭朱,并抽象動(dòng)畫提供接口方便用戶自定義擴(kuò)展和測(cè)試 AnimationFrameCallbackProvider
2 AnimationHandler向上抽象動(dòng)畫調(diào)用接口AnimationFrameCallback愚屁,方便動(dòng)畫擴(kuò)展。
3 ValueAnimator實(shí)現(xiàn)AnimationFrameCallback痕檬,單例調(diào)用AnimationHandler霎槐,實(shí)現(xiàn)doAnimationFrame 實(shí)現(xiàn)動(dòng)畫。
4 ValueAnimator專注動(dòng)畫的控制梦谜,實(shí)現(xiàn)start, stop, resume等接口