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

广西建设职业技术学校官方网站百度域名购买

广西建设职业技术学校官方网站,百度域名购买,做网站是干嘛,做网站论坛赚钱0. 相关分享 Android从屏幕刷新到View的绘制(一)之 Window、WindowManager和WindowManagerService之间的关系 Android从屏幕刷新到View的绘制(二)之Choreographer、Vsync与屏幕刷新 1. 相关类 Handler Handler中维护着它所在的…

0. 相关分享

Android从屏幕刷新到View的绘制(一)之 Window、WindowManager和WindowManagerService之间的关系
Android从屏幕刷新到View的绘制(二)之Choreographer、Vsync与屏幕刷新

1. 相关类

Handler

Handler中维护着它所在的线程的Looper,或者由用户设定的Looper。Looper分发消息Message的时候,会根据Message中设定的target,也就是Handler实例,来决定由哪个Handler来处理这个Message消息。通常我们通过重写handleMessage()方法来自定义对Message的处理。

Message

消息实体,内部的实例数据包括了:这个Message的code编号信息what,让处理者知道这是什么类型的消息,它所承载的数据obj,表示合适执行的when,表示分发给哪个Handler的target等。

它是单向链表的结构,next变量指向了下一个Message。同时对Message的对象池缓存,也定义在了Message类中,是最大长度为50的单向链表sPool。可以通过obtain()来获取合适的可复用的Message。

MessageQueue

它是访问Message的入口,管理着Message链表,与Looper一一对应,在Looper实例化的时候进行的MessageQueue实例化。提供了对Message的管理操作,例如next()获取下一个Message、removeMessages()删除指定的Message、以及我们本文要谈到的添加删除同步屏障消息。

Looper

它是一个循环主体,每个线程最多只能有一个Looper,可以通过sThreadLocal来获取Thread私有的Looper,也可以通过getMainLooper()来获取主线程的Looper从而实现与主线程的通信,或者叫做线程切换。它的loop()方法打开了死循环,循环不断地向MessageQueue索取下一个可用的Message,阻塞获取的功能在MessageQueue中实现。他能获取到同步消息、异步消息,具体线下要分发什么消息由MessageQueue来决定。

2. 核心方法

2.1 MessageQueue.postSyncBarrier()

添加同步屏障,我们可以通过MessageQueue的postSyncBarrier()来实现:

//MessageQueue.java
public int postSyncBarrier() {return postSyncBarrier(SystemClock.uptimeMillis());
}private int postSyncBarrier(long when) {synchronized (this) {//这个token用来表示这个同步屏障是谁,可以借此用来remove同步屏障final int token = mNextBarrierToken++;//复用或者获取一个Messagefinal Message msg = Message.obtain();msg.markInUse();msg.when = when;msg.arg1 = token;//但不给这个Message设置target,以此表征它是同步屏障Message prev = null;Message p = mMessages;if (when != 0) {while (p != null && p.when <= when) {prev = p;p = p.next;}}//它将会插入到还未到执行时间的Message之前。但已经到了执行时间的,不会被同步屏障挡住。if (prev != null) { // invariant: p == prev.nextmsg.next = p;prev.next = msg;} else {msg.next = p;mMessages = msg;}return token;}
}

在工程中,我们想要添加同步屏障,可以通过让MessageQueue来postSyncBarrier()的方式:

looper.getQueue().postSyncBarrier();

需要的是,就算加了同步屏障,也不代表异步消息能够立即执行,因为添加同步屏障的时候,会跳过那些执行时间已经到达,需要立即执行的任务。同步屏障Message只会插入在立即执行的Message之后非立即执行的Message之前

所以即使收到了Vsync,分发了performTraversals()的异步任务,也不一定能够立即进行View的绘制流程。如果主线程有耗时操作,就可能引发跳帧。我们这里需要知道一个知识,并不是调用完View的绘制流程就立刻刷新屏幕的,只是对一个缓存进行数据修改,等到下一次Vsync到来的时候,SurfaceFlinger才会进行渲染刷新。

如果分发的绘制消息超时了,没有执行对缓存的更新,那么SurfaceFlinger绘制的仍然是之前的缓存,所以会表现出画面卡顿,因为SurfaceFlinger只负责把缓存取出来进行渲染,而把数据写入缓存的任务由于前面Message的任务超时,导致没有及时将数据写入,所以屏幕没有变化,也就是画面卡顿。MessageQueue拿到这个异步绘制消息的时候会判断执行时间,发现超时了,说明前面卡顿导致了跳帧,就会提示下面这样的log打印消息:

Choreographer: Skipped 599 frames!  The application may be doing too much work on its main thread.

2.2 MessageQueue.next()

同步屏障的核心原理,其实就是MessageQueue在获取下个可用Message的时候,会判断获取到的是不是一个同步屏障,如果是,则继续往后找,找到可用的异步消息,将其返回出去。

Message next() {for (;;) {//阻塞获取nativePollOnce(ptr, nextPollTimeoutMillis);synchronized (this) {final long now = SystemClock.uptimeMillis();Message prevMsg = null;Message msg = mMessages;if (msg != null && msg.target == null) {//如果msg的target为null,就认为是同步屏障do {prevMsg = msg;msg = msg.next;//遍历跳过它之后所有同步消息} while (msg != null && !msg.isAsynchronous());}if (msg != null) {if (now < msg.when) {//如果将要获取得到的消息执行时间还没到,则跳过,进入下一次循环阻塞,并设置阻塞时间!nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);} else {//如果拿到的Message没问题,时间到了,也不是同步屏障,那么就把它从Message链表中移除,并返回出去mBlocked = false;if (prevMsg != null) {prevMsg.next = msg.next;} else {mMessages = msg.next;}msg.next = null;//标记为正在使用msg.markInUse();return msg;}} else {//如果message=null,也就是没有获取到Message,那么就进入到生产消费者模型的无限期等待情况,直到有Message进入,进行唤醒。nextPollTimeoutMillis = -1;}//退出looper的处理if (mQuitting) {dispose();return null;}}
}

2.3 发送异步消息

在实例化Handler的时候,可以将该Handler设为专门发送异步消息的:

public Handler(@Nullable Callback callback, boolean async) {...mLooper = Looper.myLooper();if (mLooper == null) {throw new RuntimeException("Can't create handler inside thread " + Thread.currentThread()+ " that has not called Looper.prepare()");}mQueue = mLooper.mQueue;mCallback = callback;//异步标志mAsynchronous = async;
}

后续由这个Handler发送Message的时候,会把所有由它加入MessageQueue的Message打上异步标记:

//Handler
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {//将Handler赋值给Message的target变量msg.target = this;//mAsynchronous为false,为同步消息if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);
}

当然,普通Handler也可以发送异步消息,这就需要我们手动将Message设置为异步消息,核心就是:

msg.setAsynchronous(true);

我们知道 Choreographer 中使用的都是异步消息。

http://www.tj-hxxt.cn/news/66546.html

相关文章:

  • 无锡网站建设工作室seo全站优化全案例
  • 郑州网站建设moran企业文化建设
  • 房地产做网站不引流推广方法
  • 重庆企业模板建站信息临沂seo公司稳健火星
  • 分类信息网站开发推广渠道有哪些
  • 做创业网站赚钱谷歌自然排名优化
  • 龙岗南联网站建设苏州seo网站管理
  • 胶州网站建设电商网站订烟平台官网
  • 猎头公司哪家好谷歌seo关键词优化
  • wordpress 直播 视频教程seo建站优化
  • 动漫网站开发设计思想企业门户网站的设计与实现
  • 销售平台网站建设2345网址导航手机版
  • 设计网站页面特效怎么做百度账户代运营
  • 广东东莞保安公司seo是一种利用搜索引擎的
  • 重庆网站建设seo线上免费推广平台都有哪些
  • 江阴哪家做网站便宜谷歌网页版
  • 网站注册设计百度关键词搜索查询
  • 北京建设网站公司哪家好网页模板网站
  • 互联网App网站建设方案国际国内新闻最新消息今天
  • 网站建设工作室门头腾讯广告投放平台
  • 做自己的网站挣钱百度应用商店app下载安装
  • 做网站的快捷方式代码东莞网络推广哪家公司奿
  • 网站建设及营销方案网站建设排名优化
  • 某购物网站开发项目google 优化推广
  • 做像百姓网这样网站多少钱软文营销的技巧
  • 阿里云虚拟主机与网站吗搭建网站平台需要多少钱
  • asp网站服务器架设中国百强城市榜单
  • 合肥做网站的企业公司产品营销广告宣传
  • 做网站技术路线合肥seo网站建设
  • vs2012建设空网站免费域名的网站