在ViewRootImpl创建的时刻,会获取到前面提到过过的一个关键对象Choreographer。Choreographer在一个线程中仅存在一个实例,是以在UI线程只有一个Choreographer存在。也就说,平日情况下,它相当于一个应用中的单例。
在ViewRootImpl初始化时,会实现一个Choreographer.FrameCallback(这是一个Choreographer中的内部类),并向Choreographer中post。顾名思义,FrameCallback会在每次接收到Vsync旌旗灯号时被回调。
Choreographer.java
- public interface FrameCallback {
- public void doFrame(long frameTimeNanos);
- //一旦注册到CallbackQueue中,那么
- //每次Choreographer接收到Vsync旌旗灯号时都邑回调。
- }
FrameCallback一旦被注册,那么每次收到Vsync旌旗灯号时它都邑被回调。应用它,我们可以实现会帧率的监听。
ViewRootImpl.java
- //这个办法只有在ViewRootImpl初始化时才会被调用
- private void profileRendering(boolean enabled) {
- ...
- mRenderProfiler = new Choreographer.FrameCallback() {
- @Override
- public void doFrame(long frameTimeNanos) {
- ...
- scheduleTraversals();
- //请求一个Vsync旌旗灯号,后面还会提到这个办法
- mChoreographer.postFrameCallback(mRenderProfiler);
- //每次回调时,从新将FrameCallback post到Choreographer中
- ...
- }
- };
- ...
- mChoreographer.postFrameCallback(mRenderProfiler);
- //将FrameCallback post到Choreographer中
- ...
- }
膳绫擎代码出现了一个重要办法scheduleTraversals()。下面我们看看它毕竟为何重要。 ViewRootImpl.java
- void scheduleTraversals() {
- ...
- mChoreographer.postCallback(
- Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
- //向Choreographer中post一个TraversalRunnable
- //这又是一个十分重要的对象
- ...
- }
可以看出scheduleTraversals()每次调用时会向Choreographer中post一个TraversalRunnable,它会促使Choreographer去请求一个Vsync旌旗灯号。所以这个办法的感化就是用来请求一次Vsync旌旗灯号刷新界面的。事实上,你可以看到,在invalidate()、requestLayout()等操作中,都可以或许看到它被调用。原因就是这些操作须要刷新界面,所以须要请求一个Vsync旌旗灯号来出发新界面的绘制。
ViewRootImpl.java
- final class TraversalRunnable implements Runnable {
- @Override
- public void run() {
- doTraversal();
- //开端遍历视图树,这意味着开端绘制一帧内容了
推荐阅读
当我第一次收到银行发来的“安然”邮件时,我第一反竽暌功就是这里是否有诈?因为在我看来,它实袈溱是太像垂纶邮件了。这封躺在收件箱里的邮件来源竽暌冠我银行经理的小我邮箱地>>>详细阅读
本文标题:用两张图告诉你,为什么你的App会卡顿?
地址:http://www.17bianji.com/lsqh/35508.html
1/2 1