android view工作原理,重温Android开发艺术探索之四 View工作原理

View 的工作原理

ViewRoot 和DecorView

ViewRoot对应ViewRootImpl,是连接WindowManager 和DecorView的纽带。View的三大流程都是通过ViewRoot完成的,如图所示,

![ViewRootImpl 的代码结构图]c1510b73e49547e32fbe0ae72cb71c48.png

并且当系统一些常量发生改变时也是有它监听到了处理的

在ActivityThread的attach方法中有添加这个监听,源码如下

ViewRootImpl.addConfigurationChange(Configuration newConfig),通过mH 发送消息 what = 118 的值到H 中处理 调用了 ActivityThread 的 handleConfigurationChanged

复制代码

可以说ViewRootImpl控制这整个View的绘制流程,是非常重要的,当Activity被创建时,会将DecorView添加到Window中,同时会创建ViewRootImpl对象.

ActivityThread#handleResumeActivity wm.addView(decor,l),通过WindowManager 将decor添加到window中,l是LayoutParams,核心代码如下:api25的源码

WindowManager wm;

if (r.window == null && !a.mFinished && willBeVisible) {

r.window = r.activity.getWindow();

View decor = r.window.getDecorView();

decor.setVisibility(4);

wm = a.getWindowManager();

LayoutParams l = r.window.getAttributes();

a.mDecor = decor;

l.type = 1;

l.softInputMode |= forwardBit;

if (r.mPreserveWindow) {

a.mWindowAdded = true;

r.mPreserveWindow = false;

ViewRootImpl impl = decor.getViewRootImpl();

if (impl != null) {

impl.notifyChildRebuilt();

}

}

if (a.mVisibleFromClient && !a.mWindowAdded) {

a.mWindowAdded = true;

wm.addView(decor, l);

}

} else if (!willBeVisible) {

r.hideForNow = true;

}

复制代码

wm.addView(decor, l)经过 WindowManagerImpl再到WindowManagerGlobal 中的 addView方法,在此方法里面对ViewRootImpl 进行了初始化。

ViewRootImpl root = new ViewRootImpl(view.getContext(), display);

root.setView(view, wparams, panelParentView);

复制代码

View的绘制流程是从performTraversals执行遍历开始的,经过measure,layout,draw,三个过程才能最终将一个View绘制出来。

MeasureSpec 测量规格

MeasureSpec

一个32为的int值,高2位代表SpecMode 低30位代表SpecSize。

SpecMode

UNSPECIFIED 父容器不对View做任何限制,要多大给多大。

EXACTLY 父容器已经检测出了View所需要的精确大小,这时候View的最终大小就是SpecSize所指定的值,对应与LayoutParams中的match_parent和具体数值两种模式。

AT_MOST 父容器指定了一个最大值,View不能超过这个最大值,对应wrap_content。

MeasureSpec 和 layoutParams 的对应关系

DecorView 其MeasureSpec是由自身的LayoutParams和窗口的尺寸来共同决定

普通的View 其MeasureSpec是由父容器的MeasureSpec和自身的LayoutParams来共同决定

简单来说自定义Veiw到measure这一步的时候,需要测试自身的宽高,需要widthMeasureSpec, heightMeasureSpec,宽的测量规格和高的测量规格,两者的获取方式都是一样,需要根据父容器的MeasureSpec 和自身的 宽高来得到。

View的measure过程,到这一步肯定是经过了父控件的measure过程,得到了父控件传下来的measureSpec,然后调用onMeasure,通过setMeasuredDimension 来确定自身的宽高。当然中间需要经过一些计算得到widthMeasureSpec, heightMeasureSpec。

Activity启动时去获取某一View的宽高

Activity/View#onWindowFocusChanged。

ViewTreeObserver.addOnGlobalLayoutListener()。

总结

从ViewRootImpl的构造方法中调用 loadSystemProperties()

->profileRendering()

->scheduleTraversals()

-> mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);

->doTraversal();

->performTraversals();

->performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

-> performLayout(lp, mWidth, mHeight);

-> performDraw();

完成View的三大流程。

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[重温Android开发艺术探索之四 View工作原理]http://www.zyiz.net/tech/detail-140373.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值