Android源码笔记--窗口动画管理

窗口动画管理

        Android的应用启动时,或者切换Activity时都会以动画方式显示前后两屏切换的过程。动画的原理:把一帧帧的图像按一定时间间隔显示出来就完成了。

       动画绘制需要定时驱动,通常的做法是启动一个定时消息,每个一定时间发一个消息,收到消息后输出一帧画面。Android支持VSync信号后,动画的驱动就由VSync信号来承担。窗口动画的基本元素是窗口Surface中保存的图像,通过对窗口的Surface设置不同的变换矩阵和透明度,然后强制Surface刷新,就能在屏幕上显示出窗口的变换过程。

  1.1 接收VSync信号

    WindowManagerService中有一个Choregrapher类型变量mChoreographer,如下所示:

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
		  ...
		  final Choreographer mChoreographer = Choreographer.getInstance();
		....
		
		}

 分析:Choreographer对象是通过Choregrapher类的静态方法getInstance()创建的,代码如下:

 Choreographer.java
   
    public static Choreographer getInstance() {
        return sThreadInstance.get();
    }

  分析:在getInstance()方法中调用了静态变量sThreadInstance的get()方法来获得Choreographer对象。sThreadInstance的定义如下:

 // Thread local storage for the choreographer.
    private static final ThreadLocal<Choreographer> sThreadInstance =
            new ThreadLocal<Choreographer>() {
        @Override
        protected Choreographer initialValue() {
            Looper looper = Looper.myLooper();
            if (looper == null) {
                throw new IllegalStateException("The current thread must have a looper!");
            }
            return new Choreographer(looper);
        }
    };

       分析:sThreadInstance 是一个线程局部存储变量,在它的initialValue()方法中创建了Choreographer对象并返回。这里使用线程局部存储的目的是为了在线程中只有一个Choreographer对象,因为Choreographer对象需要和线程的Looper对象关联在一起。
       看看Choreographer的构造方法:

private Choreographer(Looper looper) {
        mLooper = looper;
		//创建处理消息的Handler对象
        mHandler = new FrameHandler(looper);
        //创建接收VSync信号的FrameDisplayEventReceiver对象
		mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
        mLastFrameTimeNanos = Long.MIN_VALUE;
		//计算刷新的时间间隔
        mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
		//创建了3个CallbackQueue对象
        mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
        for (int i = 0; i <= CALLBACK_LAST; i++) {
            mCallbackQueues[i] = new CallbackQueue();
        }
    }  

    在Choregrapher的构造方法中,最重要的是创建了FrameDisplayEventReceiver对象,这个对象能够接收VSync信号。FrameDisplayEventReceiver类继承自DisplayEventReceiver类,来看看DisplayEventReceiver类的构造方法,如下:

DisplayEventReceiver.java   
   public DisplayEventReceiver(Looper looper) {
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }

        mMessageQueue = looper.getQueue();
		//native层进行初始化
        mReceiverPtr = nativeInit(this, mMessageQueue);
        mCloseGuard.open("dispose");
    }
	DisplayEventReceiver的构造方法中又调用了nativeInit()方法,它在native层对应的函数如下:
    android-5.0.0_r6\source\frameworks\base\core\jni	
    android_view_DisplayEventReceiver.cpp
	
	static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
        jobject messageQueueObj) {
    ...

    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
            receiverObj, messageQueue);
    status_t status = receiver->initialize();
    if (status) {
        String8 message;
        message.appendFormat("Failed to initialize display event receiver.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
        return 0;
    }
    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
    return reinterpret_cast<jlong>(receiver.get());
}

        分析:nativeInit()函数中创建了NativeDisplayEventReceiver对象,并调用它的initialize()函数.在NativeDisplayEventReceiver类中定义一个DisplayEventReceiver类的变量,如下:

class NativeDisplayEventReceiver : public LooperCallback {
public:
    NativeDisplayEventReceiver(JNIEnv* env,
            jobject receiverObj, const sp<MessageQueue>& messageQueue);

    status_t initialize();
    void dispose();
    status_t scheduleVsync();

private:
    jobject mReceiverObjGlobal;
    sp<MessageQueue> mMessageQueue;
    DisplayEventReceiver mReceiver;
    bool mWaitingForVsync;

    virtual int handleEvent(int receiveFd, int events, void* data);
    bool processPendingEvents(nsecs_t* outTimestamp, int32_t* id, uint32_t* outCount);
    void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count);
    void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected);
};

看看initialize():

status_t NativeDisplayEventReceiver::initialize() {
    status_t result = mReceiver.initCheck();
    //错误处理
    int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
            this, NULL);
    //错误处理
    return OK;
}

        分析:在这个方法中,调用了mReceiver对象的getFd()函数得到句柄设置到了Looper对象中,这样一旦句柄有了数据到来,就能通过Looper对象来处理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值