Android 7.1 GUI系统-窗口管理WMS-动画的执行(七)
来源:互联网 发布:java list方法 编辑:程序博客网 时间:2024/06/05 11:22
前面只是动画资源的加载过程,下面看下动画是怎么执行起来的?
前面在分析窗口申请的过程中,分析过relayoutWindow中的调用performSurfacePlacement,在这个函数的最后调用了mService.scheduleAnimationLocked(),来安排动画的执行。
void scheduleAnimationLocked() @WindowManagerService.java{ if (!mAnimationScheduled) { mAnimationScheduled = true;//通过Choreographer设置一个触发源,mChoreographer 是通过ThreadLocal保存的,所以它是一个线程中的单实例。 mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback); } }
mAnimationScheduled为true,表示当前正在scheduleanimantion,在mAnimationFrameCallback的回调中会把mAnimationScheduled再次置为false。
Choreographer设置的动画的触发源是什么?这样看下Choreographer这个类的主要功能是什么:Choreographer会接从显示系统接收定时脉冲(如Vsync),然后安排渲染下一个显示帧的工作。动画的触发源就是Vsync。
在动画框架或view层次中,应用程序通常使用较高的抽象跟Choreography间接交互,如:使用android.animation.ValueAnimator#start方法,post一个动画与渲染帧同步处理。
使用View#postOnAnimation方法,post一个Runnable,让其在下一个显示帧开始时调用。
有些情况,可能需要直接使用choreography的函数,如:
如果应用程序想在不同的线程里做渲染,可能是用GL,或者不使用animation框架、View层级,又要确保跟显示同步,这时可以使用Choreographer#postFrameCallback。
Choreography一方面接收VSYNC信号,另一方面把这一事件转发给感兴趣的人,所有希望监听VSYNC信号的对象都要在Choreography中注册。
scheduleAnimationLocked中调用的是postFrameCallback,然后直接调用了postFrameCallbackDelayed。
public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) @Choreographer.java{ postCallbackDelayedInternal(CALLBACK_ANIMATION, callback, FRAME_CALLBACK_TOKEN, delayMillis); }
这里的CALLBACK_ANIMATION是回调类型,Choreography将注册者分为三个类型:CALLBACK_INPUT,CALLBACK_ANIMATION,CALLBACK_TRAVERSAL(处理layout和draw)。
注册的回调都放在一个数组mCallbackQueues中。
当Vsync信号产生后,Choreography会通过doCallbacks,进一步调用到相应注册对象的doFrame函数。
这里回调的是WindowAnimator.java中的doFrame。
WindowAnimator.java mAnimationFrameCallback = new Choreographer.FrameCallback() { public void doFrame(long frameTimeNs) { synchronized (mService.mWindowMap) { mService.mAnimationScheduled = false; animateLocked(frameTimeNs); } } };
通过animateLocked,各种动画开始单步执行。
private void animateLocked(long frameTimeNs) {//当前时间。mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;//记录上一次的动画状态,判断动画是否结束。boolean wasAnimating = mAnimating;//先本地记录对surface的更改,最后统一统计给surfaceflinger。SurfaceControl.openTransaction();SurfaceControl.setAnimationTransaction();try {final int numDisplays = mDisplayContentsAnimators.size();//循环处理每个显示屏中的动画。for (int i = 0; i < numDisplays; i++) {final int displayId = mDisplayContentsAnimators.keyAt(i);//执行appTransition中设置的appWindow动画,updateAppWindowsLocked(displayId);//执行屏幕旋转动画,比如屏幕的横竖屏。final ScreenRotationAnimation screenRotationAnimation =displayAnimator.mScreenRotationAnimation;if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {//动画没有结束,通过setAnimating把mAnimating设置为true。setAnimating(true);}else{//动画结束了。…...}}//更新每个所有应用中的动画,包括与退出、移除app相关的。这里会执行WindowStateAnimator动画。updateWindowsLocked(displayId);updateWallpaperLocked(displayId);final WindowList windows = mService.getWindowListLocked(displayId);final int N = windows.size();for (int j = 0; j < N; j++) {//更新surface。windows.get(j).mWinAnimator.prepareSurfaceLocked(true);}}//动画还没结束,再次调用 scheduleAnimationLocked。if (mAnimating) {mService.scheduleAnimationLocked();}}finally{//统一提交给surfaceflinger处理。SurfaceControl.closeTransaction();}//在执行动画最后一步step时, mAnimating为false, wasAnimating记录是上一次mAnimating 的值,所以为true,这里将请求一次遍历,计算窗口大小,performsurface等。if (!mAnimating && wasAnimating) {mWindowPlacerLocked.requestTraversal();}}
不管那类动画,要更新动画调用的都是stepAnimationLocked,指定动画的单步,就是每个特定的时间计算动画的最新状态。如果函数true,说明动画还在进行,否则返回false。
boolean stepAnimationLocked(long currentTime) @WindowStateAnimator.java{//mWasAnimating 保存上一次的状态,通过比较mWasAnimating 和 isAnimationSet(),就知道动画是刚刚开始,还是停止了。mWasAnimating = mAnimating;//第一次执行动画,需要做些初始化。if (!mLocalAnimating) {mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),displayInfo.appWidth, displayInfo.appHeight);mAnimDx = displayInfo.appWidth;mAnimDy = displayInfo.appHeight;mAnimation.setStartTime(mAnimationStartTime != -1? mAnimationStartTime : currentTime);//已经执行过一次, mLocalAnimating置为true。mLocalAnimating = true;//表示当前正在执行动画。mAnimating = true;}// mAnimation做非null判断,因为不是每个WindowStateAnimator当前都有动画在执行。if ((mAnimation != null) && mLocalAnimating) {mLastAnimationTime = currentTime;//执行一次单步,计算当前的动画状态,返回true,表示动画还没结束。if (stepAnimation(currentTime)) {return true;}}}
如何执行一个单步。
private boolean stepAnimation(long currentTime) @WindowStateAnimator.java{currentTime = getAnimationFrameTime(mAnimation, currentTime);mTransformation.clear();final boolean more = mAnimation.getTransformation(currentTime, mTransformation);return more;}
上面的函数会根据mAnimation设置的开始时间,结合当前时间,计算出动画的新的变换值,动画的四个要素是平移、缩放、旋转、透明度,将会根据设置的属性分别调用相应类型的applyTransformation,计算变换值,保存在mTransformation中
中,其中平移、缩放、旋转由mMatrix表示,透明度由mAlpha表示。
完成动画数据的计算,接着就是真正显示到屏幕上,先由WMS对surface做更新,具体就是prepareSurfaceLocked的调用。
最后通过SurfaceControl.closeTransaction()关闭业务,将surface中的更新信息统一传给SurfaceFlinger,然后写入到framebuffer中,完成显示。
- Android 7.1 GUI系统-窗口管理WMS-动画的执行(七)
- Android 7.1 GUI系统-窗口管理WMS-窗口动画、应用动画的加载(六)
- Android 7.1 GUI系统-窗口管理WMS-窗口属性(二)
- Android 7.1 GUI系统-窗口管理WMS-窗口添加(三)
- Android 7.1 GUI系统-窗口管理WMS-窗口大小计算(五)
- Android 7.1 GUI系统-窗口管理WMS-Surface管理(四)
- Android 7.1 GUI系统-窗口管理WindowManagerService(一)
- Android 7.1 GUI系统-BufferQueue 的管理(三)
- Android6.0 WMS(六) WMS动画管理
- Android 窗口管理:如何添加窗口到WMS
- Android6.0 WMS(七) 窗口Z轴位置
- TODA WMS(仓库管理系统)简介
- WMS仓库管理系统
- 中小企业WMS管理系统
- Android源码剖析之Framework层进阶版(Wms窗口管理)
- Android6.0 WMS(十) WMS窗口动画从设置到显示框架
- Android6.0 WMS(十一) WMS窗口动画生成及播放
- 图解Android - Android GUI 系统 (2) - 窗口管理 (View, Canvas, Window Manager)
- 测试Apace是否支持解析php
- 在MinGW启动时激活环境变量
- numpy数组切片操作
- coursera-斯坦福-机器学习-吴恩达-第8周笔记-无监督学习
- 迭代器模式
- Android 7.1 GUI系统-窗口管理WMS-动画的执行(七)
- 重识java7
- java 集合
- [Leetcode] 531. Lonely Pixel I 解题报告
- A Little Java, A fewer Patterns
- CMake入门
- bootstrap CSS概述
- MacBook Pro 链接无线Wi-Fi网络问题(Wi-Fi正常打开,无法连接路由器)
- 吴恩达深度学习笔记之卷积神经网络(目标检测)