Android-怎么就不卡了呢之Choreographer,flutter蓝牙

Android-怎么就不卡了呢之Choreographer,flutter蓝牙,第1张

Android-怎么就不卡了呢之Choreographer,flutter蓝牙

mframe = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);//Message设置为异步
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doframe(mTimestampNanos, mframe);
}
}

接收到垂直同步信号后回调onVsync方法,这个方法使用handler发送带callback(Runnable类型,自身已继承)的message,最后run()中也是调用doframe();(关于这个handler的这个 *** 作详细信息逻辑,参照下面本文附录一 handler 分发message

这个message设置为了异步 (msg.setAsynchronous(true);)这意味这他有优先执行的权利,他是怎么被优先执行的呢?参照附录三 message的异步模式

综上,添加callback流程

二、执行 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 lastframeOffset = jitterNanos % mframeIntervalNanos;
//当前时间减去上一步得到的余数当作最新的始终信号时间
frameTimeNanos = startNanos - lastframeOffset;
}
//垂直同步时间上一次时间还小,就安排下次垂直,直接返回
if (frameTimeNanos < mLastframeTimeNanos) {
scheduleVsyncLocked();
return;
}
mframeInfo.setVsync(intendedframeTimeNanos, frameTimeNanos);
mframeScheduled = false;
mLastframeTimeNanos = frameTimeNanos;
}

try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, “Choreographer#doframe”);
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);

mframeInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);

mframeInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);

mframeInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);

doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
} finally {
AnimationUtils.unlockAnimationClock();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}

if (DEBUG_frameS) {
final long endNanos = System.nanoTime();
Log.d(TAG, "frame " + frame + ": Finished, took "

(endNanos - startNanos) * 0.000001f + " ms, latency "(startNanos - frameTimeNanos) * 0.000001f + " ms.");
}
}

    第一步修正判断

当前时间 startNanos = System.nanoTime();

求当前时间和垂直同步时间的差值 :jitterNanos = startNanos - frameTimeNanos;

垂直同步时间和当前时间的差值如果大于一个周期(jitterNanos >= mframeIntervalNanos)就修正一下

取插值和始终周期的余数:lastframeOffset = jitterNanos % mframeIntervalNanos;

当前时间减去上一步得到的余数当作最新的始终信号时间:frameTimeNanos = startNanos - lastframeOffset;

垂直同步时间上一次时间还小,就安排下次渲染: frameTimeNanos < mLastframeTimeNanos,直接返回

    第二步‍执行callback callback的执行顺序是:

CALLBACK_INPUT输入时间优先级最高CALLBACK_ANIMATION 动画的次之CALLBACK_TRAVERSAL UI绘制布局的再次之CALLBACK_COMMIT动画修正相关最后。 2.2 doCallbacks();

在 CallbackQueue[] mCallbackQueues在取特定类型(输入,动画,布局,Commit)的单向链表然后取出已到期的Callback/Runable执行 取出需要被执行的Actions

Action包装在CallbackRecord中,是一个单向列表,按照时间的大小顺序排列的。 取出待执行的Actions是通过CallBackQueue的extractDueCallbacksLocked()方法,可以把CallBackQueue看做是CallBack的管理类,其中还包括添加Action addCallbackLocked(),移除Action removeCallbacksLocked(),是否有带起的Anction hasDueCallbacksLocked()方法。

private final class CallbackQueue {
//链表头
private CallbackRecord mHead;
//是否存在已经到期的Action
public boolean hasDueCallbacksLocked(long now) {
return mHead != null && mHead.dueTime <= now;
}
//获取已经到期的Action
public CallbackRecord extractDueCallbacksLocked(long now) {

return callbacks;
}

//添加Action
public void addCallbackLocked(long dueTime, Object action, Object token) {

}
//移除Action
public void removeCallbacksLocked(Object action, Object token) {

}
}

执行Action

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

从callback中遍历出CallBcakRecord,挨个执行。

三、小结

Choreographer对外提供了postCallback等方法,最终他们内部都是通过调用postCallbackDelayedInternal()实现这个方法主要会做两件事情存储Act
ion请求垂直同步,垂直同步垂直同步回调立马执行Action(CallBack/Runnable)。Action一个动作内容的类型可能是CALLBACK_INPUT输入时间优先级最高CALLBACK_ANIMATION 动画的次之CALLBACK_TRAVERSAL UI绘制布局的再次之CALLBACK_COMMIT动画修正相关最后。复习Hanlder机制,我认为他是Android系统跑起来的大引擎终点关注下,handler对message的分发执行,以及“异步模式”。 附 附一、关于handler执行Message

下面是handler分发逻辑,Looper在MessageQueue得到要执行的message之后就会交给message的target(Handler类型)属性处理msg.target.dispatchMessage(msg);;

public void dispatchMessage(Message msg) {
//当msg的callback不为空的时候直接执行msg的callback它是一个Runnable对象
if (msg.callback != null) {
handleCallback(msg);
} else {
//然后再交给mCallBack,它是handler的一个属性,
//创建Handler的时候可以选择传入一个CallBack对象
//当callBack中handleMessage返回true的时候表示:True if no further handling is desired(不需要进一步处理)

if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//当mCallback处理返回为false的时候才去执行Handler自身的handleMessage()方法
handleMessage(msg);
}
}

关键逻辑在已注释,小结一下 handler的执行分发Message逻辑

    如果message的callback(runnable)属性不为空,调用这个runable的run()方法执行

private static void handleCallback(Message message) {
message.callback.run();
}

当我们使用handler.post(Runnable r)方法时候就是将r设置给message的callback

    上述条件不满足的情况下,如果handler自身的mCallback不为空的时候就会,将message交给mCallback处理,handlerMessage()结束。这个属性是在handler创建的时候传入的。mCallback是CallBack类型,他是handler的一个内部接口。

public interface Callback {
boolean handleMessage(Message msg);
}

3.当messaga 的callBak为空,且handler的mCallBack为空的时候就交给自己的handlerMessage()方法执行了。我们在自定义handler的时候可以重写这个方法对message进行相应的 *** 作。

附二 、mframeScheduled属性作用

执行callcack的时候会判断mframeScheduled属性如果为false表示没有安排渲染下一帧就直接返回,不执行。

void doframe(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
if (!mframeScheduled) {
return; // no work to do
}


mframeScheduled = false;

}

在scheduleframeLocked()方法中,将mframeScheduled值设置为ture表示安排了请求渲染下一帧。如果这时mframeScheduled为true表示已经安排了下一帧那么就返回,不添乱! 附三、Handler机制的异步模式 作用

“异步模式”的作用就是优先,asynchronous 的message在异步模式下有优先执行的权。

用法

MessageQueue使用postSyncBarrier()方法添加屏障,removeSyncBarrier()方法移除屏障这个两个方法是成对使用的。

实现原理

messageQueued的postSyncBarrier方法向messagequeue的头部添加一个target属性为null的messagemessageQueue的next()当碰到target为null的message的时候就只会在message链表中取出去“异步message”,而忽略普通的message,交给Looper做进一步分发处理。

Message next() {

for (; {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollonce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous messagin the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
} …
return msg;
}

最后相关架构及资料


/ Stalled by a barrier. Find the next asynchronous messagin the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
} …
return msg;
}

最后相关架构及资料

[外链图片转存中…(img-diFLycZx-1642395207777)]

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5708132.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存