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

微信公众号做头图的网站手机优化器

微信公众号做头图的网站,手机优化器,网页设计网站的主题,网页加速器 安卓简单来说,View的绘制流程可以概括为三个主要阶段:测量(Measure)、布局(Layout)和绘制(Draw)。 View的绘制是从ViewRootImpl的performTraversals()方法开始,遍历所有视图进…

1
2
201
3
简单来说,View的绘制流程可以概括为三个主要阶段:测量(Measure)、布局(Layout)和绘制(Draw)。
View的绘制是从ViewRootImpl的performTraversals()方法开始,遍历所有视图进行绘制操作:

private void performTraversals() {...............//measur过程performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);...............//layout过程performLayout(lp, desiredWindowWidth, desiredWindowHeight);...............//draw过程performDraw();
}

1. View的测量,计算每个View及其子View的尺寸大小(宽度和高度):

private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {if (mView == null) {return;}try {mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);} finally {Trace.traceEnd(Trace.TRACE_TAG_VIEW);}
}/*** 调用这个方法来算出一个View应该为多大。* 实际的测量工作在onMeasure()方法中进行*/
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {......if (forceLayout || needsLayout) {.....// 忽略缓存,则调用onMeasure()重新进行测量工作int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);if (cacheIndex < 0 || sIgnoreMeasureCache) {// measure ourselves, this should set the measured dimension flag backonMeasure(widthMeasureSpec, heightMeasureSpec);. . .} else {// 缓存命中,直接从缓存中取值即可,不必再测量.....}.....
}protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}

2. View的布局,确定View在父控件里的布局位置(左、上、右、下边距):

 private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,int desiredWindowHeight) {.........final View host = mView;if (host == null) {return;}host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());.........
}public void layout(int l, int t, int r, int b) {.......//调用onLayout(),ViewGroup须重写此方法onLayout(changed, l, t, r, b);.......
}

3. View的绘制,将View的内容真正绘制到屏幕上,绘制背景、canvas图层、内容、子view、padding边缘和装饰:

public void draw(Canvas canvas) {........// 绘制背景drawBackground(canvas);// 绘制内容onDraw(canvas);// 绘制子ViewdispatchDraw(canvas);// 绘制装饰,如scrollBaronDrawForeground(canvas)........
}

总结流程图:

                  +-------------------+|   ViewRootImpl    |+---------+---------+|| 调用 performTraversals()v+---------+---------+|    Measure Phase  ||     (测量阶段)     |+---------+---------+|| 递归调用 measure() -> onMeasure()v+---------+---------+|   Layout Phase    ||     (布局阶段)     |+---------+---------+|| 递归调用 layout() -> onLayout()v+---------+---------+|    Draw Phase     ||      (绘制阶段)     |+---------+---------+|| 递归调用 draw() -> onDraw()/dispatchDraw()v+-------------------+|   将内容渲染到屏幕   |+-------------------+

4
5

View的刷新机制核心方法:invalidate()requestLayout()

  1. invalidate():触发重绘
    标记View为“失效”状态,表示View的内容需要重新绘制。
    触发时机: 当View的外观(如颜色、文本、图片)发生变化,但尺寸和位置不变时,通常调用invalidate()。
public void invalidate() {  ………… if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {  mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;  final ViewParent p = mParent;  final AttachInfo ai = mAttachInfo;  if (p != null && ai != null) {  final Rect r = ai.mTmpInvalRect;  r.set(0, 0, mRight - mLeft, mBottom - mTop);  // Don't call invalidate -- we don't want to internally scroll  // our own bounds  p.invalidateChild(this, r);  }  }  
}  

可以看到,View首先通过成员变量mParent记录自己的父View,然后将AttachInfo中保存的信息告诉父View来刷新自己。
invalidate()是一种相对轻量级的刷新方式,因为它只涉及重绘,不会重新计算尺寸和位置。

  1. requestLayout():触发重新测量和布局
    标记View的尺寸或位置需要重新计算。
    触发时机: 当View的尺寸或位置发生变化时,通常调用requestLayout()。
// View类中的 requestLayout方法
public void requestLayout() {if (mMeasureCache != null) mMeasureCache.clear();if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {// Only trigger request-during-layout logic if this is the view requesting it, not the views in its parent hierarchyViewRootImpl viewRoot = getViewRootImpl();if (viewRoot != null && viewRoot.isInLayout()) {if (!viewRoot.requestLayoutDuringLayout(this)) {return;}}mAttachInfo.mViewRequestingLayout = this;}// 增加PFLAG_FORCE_LAYOUT标记,在measure时会校验此属性mPrivateFlags |= PFLAG_FORCE_LAYOUT;mPrivateFlags |= PFLAG_INVALIDATED;// 父类不为空&&父类没有请求重新布局(是否有PFLAG_FORCE_LAYOUT标志)if (mParent != null && !mParent.isLayoutRequested()) {// 调用父类的requestLayoutmParent.requestLayout();}if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {mAttachInfo.mViewRequestingLayout = null;}
}

requestLayout()会沿着View树向上查找,直到找到一个需要重新测量和布局的父View。

ViewRoot的实现类为ViewRootImpl,在这个类中的requestLayout方法与View中的并不相同:

public void requestLayout() {// 是否在处理requestLayoutif (!mHandlingLayoutInLayoutRequest) {// 检查创建view的线程是否为当前线程checkThread();mLayoutRequested = true;scheduleTraversals(); // scheduleTraversals方法调用performTraversals方法}
}

最终,会调用到ViewRootImpl的requestLayout()方法。
在下一个VSync信号到来时,如果检测到有View需要重新布局,系统会从ViewRootImpl开始,重新执行完整的「测量(Measure)、布局(Layout)和绘制(Draw)」三阶段。

VSync信号同步: Android系统会以每秒60帧的速度(16.67ms一帧)发送VSync(Vertical Synchronization)信号。

requestLayout()是一种相对重量级的刷新方式,因为它会触发完整的测量、布局和绘制流程,可能会导致性能开销,尤其是在复杂的布局中。

6

postInvalidate()是invalidate()的异步版本。
invalidate()是在主线程中调用的,所以如果要在子线程中使用就要使用Handler机制,而postInvalidate()则可在直接在子线程和主线程中使用来刷新视图。

7

http://www.dtcms.com/wzjs/365433.html

相关文章:

  • 专门做运动鞋的网站seo推广外包报价表
  • 上海seo招聘优化设计六年级下册数学答案
  • 海口做网站网络营销与管理专业是干什么的
  • 寻找扬中网站建设常见的网络营销方式有哪些
  • 龙口网站制作多少钱网络营销形式
  • 做网站的调查问卷网站源码建站
  • 自助建站源码下载大连seo
  • 济南网站建设哪家公司好各种资源都有的搜索引擎
  • php做网站子页模板北京seo排名收费
  • 哪些网站教你做美食的百度下载app
  • 昆明市建设局网站福州seo兼职
  • 爱用建站怎么样种子在线资源搜索神器
  • asp.net网站建设教程网络推广工具
  • 移动网站建设是什么网销怎么做
  • 网站开发者工作描述推广代理
  • 贵州建设厅网站怎样查询电工证南昌seo网站管理
  • 村网站开设两学一做栏目百度seo查询收录查询
  • 做企业网站备案都需要什么苹果aso优化
  • 做多肽的都有哪些网站海外推广解决方案
  • 合肥网站建设设计网络营销是做什么
  • 做网站需要学php哪些技术上海seo外包公司
  • 江西微网站建设app拉新推广项目
  • web网站开发的测试计划店铺推广软文案例
  • 税务网站建设要突出以搜索引擎营销推广
  • 网站建设详细方案亚马逊关键词搜索工具
  • 做网站找手机如何创建网站
  • 加入网站帮忙做网站福州网站优化
  • 开网络公司做网站挣钱么怎么样做推广
  • 用css做网站哪个公司的网站制作
  • 公司名称logo设计图免费新乡seo优化