Android ViewManager解读之requestLayout() 详解
尊重原创: http://blog.csdn.net/sk719887916/article/details/48464035
上篇《Android View 中invalidate()
你所不知道的那些事》主要了解了view重绘的整个流程,通过从源码的学习大家了解了view整个invalidate的整个流程,但是上篇中view的另一个重要方法 requestLayout()没做细说,本篇继续分析requestLayout()。
上文中细说了从view.invalidate()开始到view.draw()的整个过程,当然今天也从view.requestLayout()开始分析起。
requestLayout过程
顾名思义,本代码从方法名字理解为请求布局,此方法主要是将本view重新布局 ,然后绘制。当我们从某个view中调用 view.requestLayout()时,会触发super的requestLayout(),也就是整个View的invalidate(),经过判断后响应ViewParent的requestLayout(),接着获取ViewRootImpl实列调用其本身的requestLayout()
,通过执行scheduleTraversals();发送消息 ,然后ViewRoot的hander处理performTraversals(),从而做出重绘draw()动作 ,,最终还是和invalidate()执行到同一个方法上,现在我就从源码分析起
1 TextView.requestLayout()
具体某个控件 可以调用此方法,则可以让本View重新走一边测量,布局,以及绘制流程,他会调用父类的(也就是View)的requestLayout()方法,可以看下如下代码 (EP1),代码逻辑也不复杂,只要是清空测量好的数据,接着重新设置下view的AttachInfo,然后最后调用Parent的requsetLayout(),把请求权交给ViewGroup处理,
而ViewGroup呢 会得到我们的View的控制核心ViewRoot,用他的实现类ViewRootImpl去重新requestLayout()。
EP1:
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 hierarchy
ViewRootImpl viewRoot = getViewRootImpl();
if (viewRoot != null && viewRoot.isInLayout()) {
if (!viewRoot.requestLayoutDuringLayout(this)) {
return;
}
}
mAttachInfo.mViewRequestingLayout = this;
}
mPrivateFlags |= PFLAG_FORCE_LAYOUT;
mPrivateFlags |= PFLAG_INVALIDATED;
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
mAttachInfo.mViewRequestingLayout = null;
}
}
当然这种请求就是一种递归的过程, 在上面的mParent.requestLayout()其实他只是个接口,最终还是由View重载实现,还是回到上面的方法中,当ViewRoot已经请求过了,标记为不再请求布局时,才会return,可见上面的 第八行代码。
2 ViewRoot. requestLayout()
当View把控制权交由ViewRoot后,ViewRoot就会调用自己的requestLayout(),代码如下 (EP2),首先会检测修改UI的线程是否是UI主线程,当然这个代码在上篇的文章中已经说过,子线程无法更改UI的异常就是从 checkThread()里面抛出来的,接着讲本此操作标记为已经请求过,后调用 scheduleTraversals()发送消息给我们的viewRoot处理消息。
EP2:
/**
* {@inheritDoc}
*/
public void requestLayout() {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
3 scheduleTraversals( )
从上篇文章大家都知道ViewRoot本省就是handler的子类,本身就可以发送消息和处理消息,我们再来看下scheduleTraversals()(EP3),方法内部很简单,标记为已经发送了该消息,然后sendMeasse,带的参数也就是说明要执行Traversals()了,那么我再继续看看在哪里去处理这条消息的呢,
EP3:
public void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
sendEmptyMessage(DO_TRAVERSAL);
}
}
4 performTraversals( )
接着找到在handleMessage中处理了此消息,下面代码(Ep4)中的第二个case,就会处理我们请求执行的地方,发现也是和invalidate()执行一样的结果,在这里估计你也知道了,其实invalidfate()和resquestLayout()最终都会被ViewRoot在performTraversals()去处理,而这方法在 上篇《Android
View 中invalidate() 你所不知道的那些事》 中做了细说,最后还是会调用我们需要view注入进去的那个view的draw()函数,比如就是上文中TextView的darw()的方法, 这让我们更见确信Android中的view都是从子节点绘制逐步网上层递归的规程,然而开发的时候确实从父节点开始布局的,但是这不是互相矛盾的。当我代码加入一个view时,他不会先对View所在的viewGruop做准备工作,而是先对这个view进行处理,不管是measure,还是layout,都是一样的原理,直到我们的根节点被标记完所有子节点都进行完了测量,布局,绘制后
ViewRoot才会回调当前界面的view全部绘制结束,
EP4:
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case View.AttachInfo.INVALIDATE_MSG:
((View) msg.obj).invalidate();
break;
case View.AttachInfo.INVALIDATE_RECT_MSG:
final View.AttachInfo.InvalidateInfo info = (View.AttachInfo.InvalidateInfo) msg.obj;
info.target.invalidate(info.left, info.top, info.right, info.bottom);
info.release();
break;
case DO_TRAVERSAL:
if (mProfile) {
Debug.startMethodTracing("ViewRoot");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
break;
case FINISHED_EVENT:
handleFinishedEvent(msg.arg1, msg.arg2 != 0);
break;
在performTraversals()的方法最后也会发现 如下代码,告知我们的window,此view已经全部绘制完毕。
sWindowSession.finishDrawing(mWindow);
总结:
看了两篇,终于可以做总结了,还是很多疑问没有解开,那到底invalidate()和requestLayout()有什么区别,当我们通过源码分析得出不管哪个方法都会执行draw(),那么上篇中我也做了细说invalidate(),invalidate()也会执行我们的onmeasure(),layout(),draw(),但是它和resquestLayout()的不同之处,他不会清空我们测量的缓存数据,当然也不会重新回调measure,但是他会重新走Layout()过程,最终他们的目的都是重新绘制view,但是细微区别,一个要进行重新测量,一个无需进行测量。
Android ViewManager解读之requestLayout() 详解的更多相关文章
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Android图片缓存之Bitmap详解
前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. 图片缓存相关博客地址: Android图片缓 ...
- Android Design Support Library使用详解
Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的And ...
- Android 之窗口小部件详解--App Widget
Android 之窗口小部件详解--App Widget 版本号 说明 作者 日期 1.0 添加App Widge介绍和示例 Sky Wang 2013/06/27 1 App ...
- Android不规则点击区域详解
Android不规则点击区域详解 摘要 今天要和大家分享的是Android不规则点击区域,准确说是在视觉上不规则的图像点击响应区域分发. 其实这个问题比较简单,对于很多人来说根本不值得做为一篇博文写出 ...
- [Android新手区] SQLite 操作详解--SQL语法
该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法 :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解 ...
- Android中Service的使用详解和注意点(LocalService)
Android中Service的使用详解和注意点(LocalService) 原文地址 开始,先稍稍讲一点android中Service的概念和用途吧~ Service分为本地服务(LocalServ ...
- Android中SurfaceView的使用详解
Android中SurfaceView的使用详解 http://blog.csdn.net/listening_music/article/details/6860786 Android NDK开发 ...
- 《Android群英传》读书笔记 (5) 第十一章 搭建云端服务器 + 第十二章 Android 5.X新特性详解 + 第十三章 Android实例提高
第十一章 搭建云端服务器 该章主要介绍了移动后端服务的概念以及Bmob的使用,比较简单,所以略过不总结. 第十三章 Android实例提高 该章主要介绍了拼图游戏和2048的小项目实例,主要是代码,所 ...
随机推荐
- Dynamics CRM 本地插件注册器连CRMAn unsecured or incorrectly secured fault was received from the other party
今天遇到个问题,在本地打开插件注册器连接到远程CRM服务器时报如下问题 但我在CRM服务器上连接注册器是可以打开的,所以不存在账号权限这类的问题了(当然我用的是超管的账号也不可能存在),最后查询得知是 ...
- PGM:部分有向模型之条件随机场与链图模型
http://blog.csdn.net/pipisorry/article/details/52529287 贝叶斯网与马尔可夫网 [PGM:无向图模型:马尔可夫网]中例3.8和例4.8显示,贝叶斯 ...
- Premake可生成vcxproj.filters
Premake可生成vcxproj.filters (金庆的专栏) 添加 vcxproj.filters 文件可以用目录结构组织源文件. 例如premake5添加所有文件: files { ...
- C++ 中const作用
一.对const与#define的特点及区别的理解 #define只是用来做文本替换的,#define常量的生命周期止于编译期,它存在于程序的代码段,在实际程序中它只是一个常数,一个命令中的参数,并没 ...
- 程序员的自我修养-----Java开发的必须知道的几个注意点
1. 将一些需要变动的配置写在属性文件中 比如,没有把一些需要并发执行时使用的线程数设置成可在属性文件中配置.那么你的程序无论在DEV环境中,还是TEST环境中,都可以顺畅无阻地运行,但是一旦部署在P ...
- Nginx的负载均衡 - 一致性哈希 (Consistent Hash)
Nginx版本:1.9.1 我的博客:http://blog.csdn.net/zhangskd 算法介绍 当后端是缓存服务器时,经常使用一致性哈希算法来进行负载均衡. 使用一致性哈希的好处在于,增减 ...
- Android动态换肤(三、安装主题apk方式)
相比之前免安装的方式,这种方法需要用户下载并安装皮肤apk,程序写起来比免安装的要简单很多,像很多系统主题就是通过这种方式实现的. 这种方式的思路是,从所有已安装的应用程序中遍历出皮肤程序(根据特定包 ...
- 单幅图像的深度学习,对NYU数据集进行划分
针对分割问题,官方已经划分好了:http://cs.nyu.edu/~silberman/projects/indoor_scene_seg_sup.html import numpy as np i ...
- [Python]程序性能分析
有些脚本发现比预期要慢的多,就需要找到瓶颈,然后做相应的优化,参考A guide to analyzing Python performance,也可以说是翻译. 指标 运行时间 时间瓶颈 内存使用 ...
- 1073. Scientific Notation (20)
题目如下: Scientific notation is the way that scientists easily handle very large numbers or very small ...