android动画效果实现机制,Android Framework 窗口子系统 (06)窗口动画之...

系列文章解读&说明:

Android Framework 窗口子系统 的 分析主要分为以下部分:

(01)WindowMangerService基础知识

(02)应用进程和WindowManagerService之间的关系

(03)窗口显示次序

(04)确定窗口尺寸

(05)窗口布局说明

(06)窗口动画之Choreographer机制

(07)窗口动画之Animation & Animator

(08)窗口动画之动画系统

本模块分享的内容:窗口动画Choreographer机制

本章关键点总结 & 说明:

20190705172409423.png

导图是不断迭代的,该图主要关注?思维导图中左上:Choreographer机制?部分即可,主要说明Choreographer机制的对外接口,这里做了简单的源码分析,对其原理有一定的了解。放大?Choreographer机制?的局部图,效果如下:

20190705172520276.png

Choreographer机制说明:该机制是android 4.2之后 推出的API,和handler的post机制类似,区别在于Choreographer的处理时机是?屏幕的垂直同步Vsync事件到来之时,其处理回调的过程被当作渲染下一帧工作的一部分。

对于动画而言,Choreographer对外接口说明如下:

postCallback(int callbackType, Runnable action, Object token):下一次Vsync时执行action参数指定的操作。callbackType的参数可以是CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSAL

postCallbackDelayed(...):同上,只是加了延迟时间而已。

postFrameCallback(int callbackType, Runnable action, Object token):分析源码可知,就是封装了postCallback,callbackType参数为CALLBACK_ANIMATION而已。

postFrameCallbackDelayed(...):同上,只是加了延迟时间而已。

后面会通过源码进行深入的说明。接下来开始进入Choreographer源码解读

1?Choreographer分析

在Activity启动过程,执行完onResume后,层层调用后会到addView(),再到ViewRootImpl构造器,代码如下:

public ViewRootImpl(Context context, Display display) {

//...

mChoreographer = Choreographer.getInstance();

//...

}

继续分析getInstance,代码如下:

public static Choreographer getInstance() {

return sThreadInstance.get();

}

继续分析sThreadInstance.get,代码如下:

private static final ThreadLocal sThreadInstance =

new ThreadLocal() {

@Override

protected Choreographer initialValue() {

Looper looper = Looper.myLooper();//获取当前线程looper

//...

return new Choreographer(looper);

}

};

当前线程为UI线程,因此get获得的就是Choreographer(looper);继续分析Choreographer构造器,代码如下:

private Choreographer(Looper looper) {

mLooper = looper;

mHandler = new FrameHandler(looper);//handler对象

//用于接收VSync信号

mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;

//是指上一次帧绘制时间点;

mLastFrameTimeNanos = Long.MIN_VALUE;

//帧间时长,一般等于16.7ms

mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());

//创建回调对象

mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];

for (int i = 0; i <= CALLBACK_LAST; i++) {

mCallbackQueues[i] = new CallbackQueue();

}

}

接下来我们关注两个变量:FrameHandler和FrameDisplayEventReceiver。

1.1?FrameHandler分析

代码如下:

private final class FrameHandler extends Handler {

public FrameHandler(Looper looper) {

super(looper);

}

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case MSG_DO_FRAME:

doFrame(System.nanoTime(), 0);

break;

case MSG_DO_SCHEDULE_VSYNC:

doScheduleVsync();

break;

case MSG_DO_SCHEDULE_CALLBACK:

doScheduleCallback(msg.arg1);

break;

}

}

}

这里可知:handler可以处理三种消息,帧消息,VSYNC,CALLBACK。

1.2?FrameDisplayEventReceiver创建

代码如下:

private final class FrameDisplayEventReceiver extends DisplayEventReceiver

implements Runnable {

private boolean mHavePendingVsync;

private long mTimestampNanos;

private int mFrame;

public FrameDisplayEventReceiver(Looper looper) {

super(looper);

}

@Override

public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {

if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {

scheduleVsync();

return;

}

long now = System.nanoTime();

if (timestampNanos > now) {

timestampNanos = now;

}

if (mHavePendingVsync) {

} else {

mHavePendingVsync = true;

}

mTimestampNanos = timestampNanos;

mFrame = frame;

Message msg = Message.obtain(mHandler, this);

msg.setAsynchronous(true);

mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);

}

@Override

public void run() {

mHavePendingVsync = false;

doFrame(mTimestampNanos, mFrame);

}

}

这里当有Vsync信号上报时会回调onVSync方法,它使用handler发送消息给主线程Looper,消息自带callback,内容为FrameDisplayEventReceiver。 当主线程Looper执行到该消息时调用FrameDisplayEventReceiver.run()方法。这里沿着run方法,继续分析doFrame,代码如下:

void doFrame(long frameTimeNanos, int frame) {

final long startNanos;

synchronized (mLock) {

if (!mFrameScheduled) {

return; // no work to do

}

startNanos = System.nanoTime();

final long jitterNanos = startNanos - frameTimeNanos;

if (jitterNanos >= mFrameIntervalNanos) {

final long skippedFrames = jitterNanos / mFrameIntervalNanos;

final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;

frameTimeNanos = startNanos - lastFrameOffset;

}

if (frameTimeNanos < mLastFrameTimeNanos) {

scheduleVsyncLocked();

return;

}

mFrameScheduled = false;

mLastFrameTimeNanos = frameTimeNanos;

}

doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);

doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);

doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);

}

这里每调用一次scheduleFrameLocked(),则mFrameScheduled=true,能执行一次doFrame()操作,执行完doFrame()并设置mFrameScheduled=false;

最终有3个回调类别,如下所示:

INPUT:输入事件

ANIMATION:动画

TRAVERSAL:窗口刷新,执行measure/layout/draw操作

这里继续分析doCallbacks,代码如下:

void doCallbacks(int callbackType, long frameTimeNanos) {

CallbackRecord callbacks;

synchronized (mLock) {

final long now = SystemClock.uptimeMillis();

callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(now);

mCallbacksRunning = true;

}

try {

for (CallbackRecord c = callbacks; c != null; c = c.next) {

c.run(frameTimeNanos);

}

} finally {

synchronized (mLock) {

mCallbacksRunning = false;

do {

final CallbackRecord next = callbacks.next;

recycleCallbackLocked(callbacks);

callbacks = next;

} while (callbacks != null);

}

}

}

这段代码总结如下:

只要callback不为null,则开始执行相应回调的run()方法;

回收callbacks,加入对象池mCallbackPool,就是说callback一旦执行完成,则会被回收。

接下来我们继续分析下CallbackRecord类,代码如下:

private static final class CallbackRecord {

public CallbackRecord next;

public long dueTime;

public Object action; // Runnable or FrameCallback

public Object token;

public void run(long frameTimeNanos) {

if (token == FRAME_CALLBACK_TOKEN) {

((FrameCallback)action).doFrame(frameTimeNanos);

} else {

((Runnable)action).run();

}

}

}

这里的回调run()有两种情况:

当token为FRAME_CALLBACK_TOKEN,则执行该对象的doFrame()方法。

当token为其他类型时,则执行该对象的run()方法。

2 动画显示过程

WMS是通过调用scheduleAnimationLocked()方法来设置mFrameScheduled=true来触发动画, 下面分析动画控制的过程。代码如下:

void scheduleAnimationLocked() {

if (!mAnimationScheduled) {

mAnimationScheduled = true;

mChoreographer.postCallback(

Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);

}

}

只有当mAnimationScheduled=false时,才会执行postCallback(),其中参数为mAnimator.mAnimationFrameCallback。

2.1 这里对参数mAnimator.mAnimationFrameCallback进行分析

mAnimator该对象类型为WindowAnimator,在WMS中定义:

private WindowManagerService(

//...

mAnimator = new WindowAnimator(this);

//...

}

WindowAnimator的构造器如下:

WindowAnimator(final WindowManagerService service) {

mService = service;

mContext = service.mContext;

mPolicy = service.mPolicy;

mAnimationRunnable = new Runnable() {

@Override

public void run() {

synchronized (mService.mWindowMap) {

mService.mAnimationScheduled = false;

animateLocked();

}

}

};

}

分析到这里,如果下一个VSync到来,将会执行到animateLocked方法。

2.2 对mChoreographer.postCallback进行分析

postCallback代码实现如下:

public void postCallback(int callbackType, Runnable action, Object token) {

postCallbackDelayed(callbackType, action, token, 0);

}

继续分析postCallbackDelayed,代码如下:

public void postCallbackDelayed(int callbackType,

Runnable action, Object token, long delayMillis) {

//容错处理...

postCallbackDelayedInternal(callbackType, action, token, delayMillis);

}

继续分析postCallbackDelayedInternal,代码如下:

// 参数说明:

/*callbackType为动画

action为mAnimationFrameCallback

token为FRAME_CALLBACK_TOKEN

delayMillis=0

*/

private void postCallbackDelayedInternal(int callbackType,

Object action, Object token, long delayMillis) {

synchronized (mLock) {

final long now = SystemClock.uptimeMillis();

final long dueTime = now + delayMillis;

//添加到 mCallbackQueues队列

mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);

if (dueTime <= now) {

scheduleFrameLocked(now);

} else {

//发送消息MSG_DO_SCHEDULE_CALLBACK

Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);

msg.arg1 = callbackType;

msg.setAsynchronous(true);

mHandler.sendMessageAtTime(msg, dueTime);

}

}

}

这里最后发送的消息类型是MSG_DO_SCHEDULE_CALLBACK,handler收到后处理如前面所示:

private final class FrameHandler extends Handler {

public void handleMessage(Message msg) {

switch (msg.what) {

case MSG_DO_FRAME:

doFrame(System.nanoTime(), 0);

break;

case MSG_DO_SCHEDULE_VSYNC:

doScheduleVsync();

break;

case MSG_DO_SCHEDULE_CALLBACK:

doScheduleCallback(msg.arg1);

break;

}

}

}

这里继续分析doScheduleCallback,代码如下所示:

void doScheduleCallback(int callbackType) {

synchronized (mLock) {

if (!mFrameScheduled) {

final long now = SystemClock.uptimeMillis();

if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {

scheduleFrameLocked(now);

}

}

}

}

继续分析scheduleFrameLocked,代码实现如下:

private void scheduleFrameLocked(long now) {

if (!mFrameScheduled) {

mFrameScheduled = true;

if (USE_VSYNC) {

if (isRunningOnLooperThreadLocked()) {

scheduleVsyncLocked();//当运行在Looper线程,则立刻调度vsync

} else {

//发送给UI线程

Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);

msg.setAsynchronous(true);

mHandler.sendMessageAtFrontOfQueue(msg);

}

} else {

//...

}

}

}

这里注意,当运行在其他线程时,通过发送一个消息到Looper线程,然后通过handler处理消息执行scheduleVsyncLocked();

接下来分析scheduleVsyncLocked的核心实现,代码如下:

private void scheduleVsyncLocked() {

mDisplayEventReceiver.scheduleVsync();

}

继续分析mDisplayEventReceiver的scheduleVsync实现,代码如下:

public void scheduleVsync() {

if (mReceiverPtr == 0) {

Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "

+ "receiver has already been disposed.");

} else {

nativeScheduleVsync(mReceiverPtr);

}

}

这里nativeScheduleVsync函数的实现,代码如下:

static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {

sp receiver =

reinterpret_cast(receiverPtr);

status_t status = receiver->scheduleVsync();

//容错处理...

}

这里继续分析receiver->scheduleVsync();,代码实现如下:

status_t NativeDisplayEventReceiver::scheduleVsync() {

if (!mWaitingForVsync) {

// Drain all pending events.

nsecs_t vsyncTimestamp;

int32_t vsyncDisplayId;

uint32_t vsyncCount;

//清除所有的pending事件,只保留最后一次vsync

processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);

status_t status = mReceiver.requestNextVsync();

mWaitingForVsync = true;

}

return OK;

}

这里关注mReceiver.requestNextVsync();代码实现如下:

status_t DisplayEventReceiver::requestNextVsync() {

if (mEventConnection != NULL) {

mEventConnection->requestNextVsync();

return NO_ERROR;

}

return NO_INIT;

}

该方法的作用请求下一次Vsync信息处理,当Vsync信号到来,由于mFrameScheduled = true,则继续执行第1部分中最后部分中的CallbackRecord.run()方法。

使用说明:避免在执行动画渲染的前后在主线程放入耗时操作,否则会造成卡顿感,影响用户体验。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值