【Android】布局

Window、DecorView、ViewRootImpl

【Android】布局_第1张图片
1.点击桌面APP图标时,Launcher的startActivity()方法,通过Binder通信,调用system_server进程中AMS服务的startActivity方法,发起启动请求
3.2.system_server进程接收到请求后,向Zygote进程发送创建进程的请求
Zygote进程fork出App进程,并执行ActivityThread的main方法,创建ActivityThread线程,初始化MainLooper,主线程Handler,同时初始化ApplicationThread用于和AMS通信交互
4.App进程,通过Binder向sytem_server进程发起attachApplication请求,这里实际上就是APP进程通过Binder调用sytem_server进程中AMS的attachApplication方法,上面我们已经分析过,AMS的attachApplication方法的作用是将ApplicationThread对象与AMS绑定
5.system_server进程在收到attachApplication的请求,进行一些准备工作后,再通过binder IPC向App进程发送handleBindApplication请求(初始化Application并调用onCreate方法)和scheduleLaunchActivity请求(创建启动Activity)
6.App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送BIND_APPLICATION和LAUNCH_ACTIVITY消息,这里注意的是AMS和主线程并不直接通信,而是AMS和主线程的内部类6.ApplicationThread通过Binder通信,ApplicationThread再和主线程通过Handler消息交互。 ( 这里猜测这样的设计意图可能是为了统一管理主线程与AMS的通信,并且不向AMS暴露主线程中的其他公开方法,大神可以来解析下)
7.主线程在收到Message后,创建Application并调用onCreate方法,再通过反射机制创建目标Activity,并回调Activity.onCreate()等方法
8.到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染后显示APP主界面
————————————————
版权声明:本文为CSDN博主「学也不知义」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hzwaill...

Window是一个抽象类,表示一个窗口,具体实现类是PhoneWindow。
Window分为3种,APP Window,系统Window和子Window,子Window必须依附在别的Window上。
setContentView中会生成一个PhoneWindow对象,这个PhoneWindow对象会生成DecorView,DecorView将会添加标题栏和递归解析content布局,WindowManager会委托WindowManagerGlobal添加,会生成一个新的ViewRootImpl,并把DecorView和ViewRootImpl绑定起来,WindowManagerGlobal会通过几个数组来储存这些信息。
private final ArrayList mViews = new ArrayList();
private final ArrayList mRoots = new ArrayList();
private final ArrayList mParams = new ArrayList();
private final ArraySet mDyingViews = new ArraySet();
一个Window对应一个DecorView,对应一个ViewRootImpl。

ViewRootImpl会负责与WMS进行通信,并控制整个视图的绘制。
其中绘制的起点是ViewRootImpl.performTraversals -> ViewRootImpl.performMeasure -> ViewRootImpl.performLayout - > ViewRootImpl.performDraw调用作为根视图DecorView的measure,layout,draw方法来遍历视图树。
【Android】布局_第2张图片
作者:豆沙包67
链接:https://www.jianshu.com/p/a75...
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

DecorView是一个Framelayout,从这里进入View的measure,layout,draw过程。

Measure、Layout、Draw

测量种类分为3种,测量相关都要通过MeasureSpec
1.MeasureSpec.EXACTLY:确定模式,父容器希望子视图View的大小是固定,也就是specSize大小。
2.MeasureSpec.AT_MOST:最大模式,父容器希望子视图View的大小不超过父容器希望的大小,也就是不超过specSize大小。
3.MeasureSpec.UNSPECIFIED: 不确定模式,子视图View请求多大就是多大,父容器不限制其大小范围,也就是size大小。
从content开始整个测量的流程,content比较特殊,它测量的初始参数由windows决定。
1.当DecorView根布局的子视图View宽高为一个确定值childDimension时,该View的测量模式为MeasureSpec.EXACTLY,测量大小就是childDimension。
2.当子视图View宽高为MATCH_PARENT时,该View的测量模式为MeasureSpec.EXACTLY,测量大小是父容器DecorView规定的大小,为整个屏幕大小MATCH_PARENT。
3.当子视图View宽高为WRAP_CONTENT时,该View的测量模式为MeasureSpec.AT_MOST,测量大小是父容器DecorView规定的大小,为整个屏幕大小MATCH_PARENT。

1.View的measure方法是final类型的,子类不可以重写,子类可以通过重写onMeasure方法来测量自己的大小,当然也可以不重写onMeasure方法使用系统默认测量大小。
2.View测量结束的标志是调用了View类中的setMeasuredDimension成员方法,言外之意是,如果你需要在自定义的View中重写onMeasure方法,在你测量结束之前你必须调用setMeasuredDimension方法测量才有效。
3.在Activity生命周期onCreate和onResume方法中调用View.getWidth()和View.getMeasuredHeight()返回值为0的,是因为当前View的测量还没有开始,这里关系到Activity启动过程,文章开头说了当ActivityThread类中的performResumeActivity方法执行之后才将DecorView添加到PhoneWindow窗口上,开始测量。在Activity生命周期onCreate在中performResumeActivity还为执行,因此调用View.getMeasuredHeight()返回值为0。
4.子视图View的大小是由父容器View和子视图View布局共同决定的。
【Android】布局_第3张图片

1.视图View的布局逻辑是由父View,也就是ViewGroup容器布局来实现的。因此,我们如果自定义View一般都无需重写onMeasure方法,但是如果自定义一个ViewGroup容器的话,就必须实现onLayout方法,因为该方法在ViewGroup是抽象的,所有ViewGroup的所有子类必须实现onLayout方法。
2.当我们的视图View在布局中使用 android:visibility=”gone” 属性时,是不占据屏幕空间的,因为在布局时ViewGroup会遍历每个子视图View,判断当前子视图View是否设置了 Visibility==GONE,如果设置了,当前子视图View就会添加到父容器上,因此也就不占据屏幕空间。具体可以参考2-4节。

3.必须在View布局完之后调用getHeight()和getWidth()方法获取到的View的宽高才大于0。具体可以参考2-3节。

1.View绘制的画布参数canvas是由surface对象获得,言外之意,View视图绘制最终会绘制到Surface对象去。关于Surface内容参考3-1节。
2.由3-2小节我们了解到,父类View绘制主要是绘制背景,边框渐变效果,进度条,View具体的内容绘制调用了onDraw方法,通过该方法把View内容的绘制逻辑留给子类去实现。因此,我们在自定义View的时候都一般都需要重写父类的onDraw方法来实现View内容绘制。
3.不管任何情况,每一个View视图都会绘制 scrollBars滚动条,且绘制滚动条的逻辑是在父类View中实现,子类无需自己实现滚动条的绘制。其实TextView也是有滚动条的,可以通过代码让其显示滚动条和内容滚动效果。你只需在TextView布局设置android:scrollbars=”vertical”属性,且在代码中进行如下设置
textView.setMovementMethod(ScrollingMovementMethod.getInstance());
这样既可让你的TextView内容可以滑动,且有滚动条。
4.ViewGroup绘制的过程会对每个子视图View设置布局容器动画效果,如果你在ViewGroup容器布局里面设置了如下属性的话:
android:animateLayoutChanges="true"
————————————————
版权声明:本文为CSDN博主「废墟的树」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/feiducl...

FrameLayout、LinearLayout、RelativeLayout

最常用的三个布局
FrameLayout
较为简单,各个控件之间不互相干扰。

LinearLayout
会先测量一次没有weight的控件大小,再把剩余的空间再测量一轮由weight分

RelativeLayout
测量的时候确定好坐标

沉浸式

在Windows上除了content,可能还会出现titlebar,状态栏、ActionBar、导航栏
1.FullScrren会隐藏状态栏
2.NoTitleBar 会隐藏titleBar
3.NoACtionBar 会隐藏ActionBar
// todo

你可能感兴趣的:(android)