当前位置: 首页 > news >正文

淘宝联盟怎么新建网站盐城优化办

淘宝联盟怎么新建网站,盐城优化办,兰州模板网站建设,域名注册后怎么备案每一帧的绘制是生产者消费者模式Android 整个「每一帧渲染到屏幕」的链路,从 App 端的 ViewRootImpl 到最终显示在面板(Display),本质上就是 典型的生产者-消费者模型。核心组件与数据流如下:生产者(Produc…

 每一帧的绘制是生产者消费者模式

Android 整个「每一帧渲染到屏幕」的链路,从 App 端的 ViewRootImpl 到最终显示在面板(Display),本质上就是 典型的生产者-消费者模型。核心组件与数据流如下:

  1. 生产者(Producer)
    • App 主线程的 ChoreographerViewRootImplSurfaceFlingerBufferQueue
    • 每 16.7 ms(60 Hz)收到 VSync 信号后,主线程/RenderThread 把 UI 树绘制到一块 GraphicBuffer(OpenGL / Vulkan 渲染结果)。
    • 绘制完成把这块 buffer queueSurfaceFlinger 的 BufferQueue → 生产者完成一次“生产”。

  2. 缓冲区(Queue)
    BufferQueue 是 Binder 跨进程对象,内部维护 最多 2~3 个 slot(双缓冲/三缓冲)。
    • 当 App 把 buffer 放入队列后,会立即拿到下一块空闲 buffer 继续下一帧的生产。

  3. 消费者(Consumer)
    SurfaceFlinger 作为消费者进程,在收到 HW-VSync软件 VSync 后,从 BufferQueue dequeue 最新一帧 buffer。
    • 把该帧做合成(Composition,可能叠加多图层),然后提交给 Display HAL(HWComposer),最终驱动面板刷新。

  4. 同步与背压
    • 如果 App 生产过快(丢帧),BufferQueue slot 满,dequeueBuffer阻塞 生产者,形成背压。
    • 如果生产过慢,消费者拿不到新 buffer,就继续显示上一帧 → 用户感觉卡顿。

App 每帧把渲染结果“生产”进 BufferQueue,SurfaceFlinger 作为“消费者”取帧送显;这套机制就是 生产者-消费者 + 双/三缓冲 + VSync 同步 的经典实现。

vsync信号来临到生成一帧流程

Choreographer.FrameDisplayEventReceiver.onVsync

Vsync信号来临会调用到android的Choreographer.FrameDisplayEventReceiver.onVsync方法

在该方法中发送异步消息到主线程

public void onVsync(long timestampNanos, long physicalDisplayId, int frame,VsyncEventData vsyncEventData) {//发送异步消息
Message msg = Message.obtain(mHandler, this);
//true这里是异步消息
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);

 

处理异步消息

//主线程调用异步消息,开始绘制流程
@Override
public void run() {mHavePendingVsync = false;doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
}

各种事件开始处理

void doFrame(long frameTimeNanos, int frame,DisplayEventReceiver.VsyncEventData vsyncEventData) {
//输入事件 触摸、按键、轨迹球、鼠标事件
doCallbacks(Choreographer.CALLBACK_INPUT, frameData, frameIntervalNanos);mFrameInfo.markAnimationsStart();
//普通动画 ValueAnimator、ObjectAnimator、View.animate() 等属性动画的下一帧计算。
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameData, frameIntervalNanos);
//insets 动画 与系统窗口(IME、系统栏)同步的边衬动画,比如键盘弹出/收回动画。
doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameData,frameIntervalNanos);mFrameInfo.markPerformTraversalsStart();
//遍历 / 刷新布局 ViewRootImpl.scheduleTraversals() 安排的 performTraversals()——测量、布局、绘制;invalidate() 最终走到这里。
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameData, frameIntervalNanos);
//帧提交 / 收尾 在 draw() 完成、SurfaceFlinger 消费前做最后的 Buffer 提交 与 帧统计;也用于 FrameMetrics 打点。
doCallbacks(Choreographer.CALLBACK_COMMIT, frameData, frameIntervalNanos);

Choreographer.doCallbacks(Choreographer.CALLBACK_TRAVERSAL

处理绘制相关流程

void doCallbacks(int callbackType, FrameData frameData, long frameIntervalNanos) {try {Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);for (CallbackRecord c = callbacks; c != null; c = c.next) {//分发事件,这里调用的是ViewRootImpl.mTraversalRunnable.runc.run(frameData);}

开始刷新

ViewRootImpl.mTraversalRunnable.run

final class TraversalRunnable implements Runnable {@Overridepublic void run() {//开始度量,布局,绘制doTraversal();}
}void doTraversal() {
//如果没有请求刷新,Vsync信号来将不会刷新if (mTraversalScheduled) {//修改标志位mTraversalScheduled = false;//移除消息屏障,这个执行后才会执行普通消息mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);if (mProfile) {Debug.startMethodTracing("ViewAncestor");}//开始测量,布局,绘制performTraversals();if (mProfile) {Debug.stopMethodTracing();mProfile = false;}}
}

ViewRootImpl.performTraversals

//开始测量,布局,绘制
        performTraversals();

private void performTraversals() {
//度量
performMeasure()
//布局
performLayout(lp, mWidth, mHeight);
//绘制
performDraw()
}

ViewRootImpl.performMeasure

private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {if (mView == null) {return;}Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");try {//顶层View开始下发度量mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);} finally {Trace.traceEnd(Trace.TRACE_TAG_VIEW);}
}

ViewRootImpl.performLayout

private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,int desiredWindowHeight) {final View host = mView;
if (host == null) {return;
}try {//顶层View开始度量host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());

ViewRootImpl.performDraw

private boolean performDraw() {
try {boolean canUseAsync = draw(fullRedrawNeeded, usingAsyncReport && mSyncBuffer);if (usingAsyncReport && !canUseAsync) {mAttachInfo.mThreadedRenderer.setFrameCallback(null);usingAsyncReport = false;}
} 
}private boolean draw(boolean fullRedrawNeeded, boolean forceDraw) {
drawSoftware}private boolean draw(boolean fullRedrawNeeded, boolean forceDraw) {// 如果脏区域非空、正在做动画,或无障碍焦点变化,则真正进入绘制if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {// ---- 硬件加速路径(默认开启) ----if (isHardwareEnabled()) {// 把 View 树封装成 DisplayList,通过 Binder 交给 RenderThread// 由 GPU 异步完成真正的绘制与上屏mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);// ---- 软件绘制路径(硬件加速关闭或 Surface 不支持) ----} else {// 直接在 UI 线程用 Skia/Canvas 把 View 画到 Surfaceif (!drawSoftware(surface, mAttachInfo, xOffset, yOffset,scalingRequired, dirty, surfaceInsets)) {// 软件绘制失败,直接返回 falsereturn false;}}}// 本次绘制流程结束,返回是否使用异步帧报告return useAsyncReport;}private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
mView.draw(canvas);}

生产数据交给消费者消费

android处理完后会交给消费者消费

请求下一次Vsync信号来需要刷新流程

View.assignParent

void assignParent(ViewParent parent) {if (mParent == null) {mParent = parent;} else if (parent == null) {mParent = null;} else {throw new RuntimeException("view " + this + " being added, but"+ " it already has a parent");}
}

最顶层View

最顶层View的mParent是通过ViewRootImpl的setView方法添加的时候注入的

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId) 
view.assignParent(this);
}

View树下发Parent

是通过ViewGroup设置下发的

是通过ViewGroup设置下发的
private void addViewInner(View child, int index, LayoutParams params,boolean preventRequestLayout)if (preventRequestLayout) {child.assignParent(this);
} else {child.mParent = this;
}

View.Invalidate

内容变化但是大小不变化会触发该方法,该方法在硬件加速打开的时候不会出现崩溃,不会进行线程检查checkThread()

在调节满足的情况下ViewGroup的invalidateChil逐级上报,最后上报到顶层ViewGroup中

最顶层是

void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,boolean fullInvalidate) {
if (p != null && ai != null && l < r && t < b) {final Rect damage = ai.mTmpInvalRect;damage.set(l, t, r, b);p.invalidateChild(this, damage);
}
public final void invalidateChild(View child, final Rect dirty) {final AttachInfo attachInfo = mAttachInfo;//开启硬件加速后执行该位置if (attachInfo != null && attachInfo.mHardwareAccelerated) {// HW accelerated fast pathonDescendantInvalidated(child, child);return;}


调用流程是

View.invalidate->ViewGroup.invalidateChild->ViewGroup.invalidateChild->……->最顶层ViewGroup.invalidateChild->ViewRootImpl.invalidateChild

View.requestLayout

控件大小变化后会执行该方法,方法在硬件加速开启的情况下也会进行线程检查

会调用ViewGroup的requestLayout

public void requestLayout() {if (mParent != null && !mParent.isLayoutRequested()) {mParent.requestLayout();
}

调用流程是View.requestLayout->ViewGroup.requestLayout->ViewGroup.requestLayout->……->最顶层ViewGroup.requestLayout->ViewRootImpl.requestLayout

ViewRootImpl.requestLayout

@Override
public void requestLayout() {if (!mHandlingLayoutInLayoutRequest) {//线程检查checkThread();mLayoutRequested = true;//开始消息屏障,入队scheduleTraversals();}
}

ViewRootImpl.scheduleTraversals消息屏障入队

void scheduleTraversals() {//设置标志位,每一次Vsync期间只会插入一次,没有移除消息屏障不会再次插入if (!mTraversalScheduled) {//修改标志位mTraversalScheduled = true;//开启消息屏障,记录屏障tokenmTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();//将消息放入Choreographer中mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);notifyRendererOfFramePending();pokeDrawLockIfNeeded();}
}

Choreographer.postCallback入队刷新消息

入队消息,等待vsync信号来临取出

private void postCallbackDelayedInternal(int callbackType,Object action, Object token, long delayMillis) {
synchronized (mLock) {//消息进入队列中mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);}

硬件加速开启后View刷新

在开启硬件加速的情况下,View的大小未改变,之改变内存,是不会进行线程检查的

不会检查线程,只有大小改变了触发了requestLayout会崩溃

View.invalidateChild
public final void invalidateChild(View child, final Rect dirty) {final AttachInfo attachInfo = mAttachInfo;//开启硬件加速后执行该位置if (attachInfo != null && attachInfo.mHardwareAccelerated) {// HW accelerated fast pathonDescendantInvalidated(child, child);return;}
View.onDescendantInvalidated@Override
public void onDescendantInvalidated(@NonNull View child, @NonNull View descendant) {// TODO: Re-enable after camera is fixed or consider targetSdk checking this// checkThread();if ((descendant.mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {mIsAnimating = true;}
//开启硬件加速后不会检查线程invalidate();
}

http://www.dtcms.com/a/429153.html

相关文章:

  • 南阳网站建设域名公司大连网站建设策划
  • 扁平化资讯网站模板世界十大市场调研公司
  • 建设企业网站e路护航官网企业端外包一个项目多少钱
  • 黑龙江两学一做网站同城引流用什么软件
  • 网站制作哪些公司好外贸平台网站有哪些
  • vs网站制作如何让百度快速收录网站
  • 简单公司网站源码WordPress文章投票
  • 基于大数据的美食分析可视化平台: 美食大数据深度分析系统Python+Hadoop+Spark+LSTM预测(优秀项目)✅
  • 回龙观做网站怎么在网站后面制作官网俩个字
  • 上街免费网站建设建设视频网站费用吗
  • 网站 备案 异地steam账号注册网站
  • 凡客网站建设怎么样张家港质监站网址
  • Stable Diffusion原理解析
  • CPP——OJ试题,string、vector、类(题三)初步应用
  • 制作天下网站织梦网站后台视频教程
  • 保定网站建设服务wordpress post_type
  • 英语形态学基础概念
  • 创业公司造APP:是自建“御林军”还是聘请“外援军团”?优雅草卓伊凡
  • 藁城网站建设为什么语音转文字里面没有海南的
  • 一站式AI数字人创作平台,让AI创作触手可及(文末有安装包)
  • WordPress搭建社区网站2023引流软件
  • 营口 微网站建设WordPress万级数据优化
  • 网站建设学习学校展台展馆设计搭建
  • asp网站经常 响应做视频付费网站
  • asp网站怎么仿站甘肃营销型网站制作
  • 构建AI应用的技术基石:Hugging Face平台架构与使用流程解析
  • linux部署postgreSQL和redis
  • 网站建设程序编制校园信息网站开发与设计
  • 告别AI黑盒:Amazon Augmented AI,为人机协作按下“加速键”
  • 标志设计logo网站岳阳网站建设有哪些