标签:
本篇模拟三个角色:Android 架构师-小福、Android 控件开发工程师-小黑、 Android 开发工程师-小白,下面按照三个角色不同角度分析measure过程。
小福负责分享:
public final class ViewRootImpl extends Handler implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
// 1 所有子视图的requestLayout方法,最总都会触发根视图此方法
public void requestLayout() {
checkThread();
// 需要重新布局
mLayoutRequested = true;
scheduleTraversals();
}
// 调度遍历
public void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
.....
// 当前类继承自Handler,发出一个空消息,目的是加入Message队列
sendEmptyMessage(DO_TRAVERSAL);
}
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
...
case DO_TRAVERSAL:
...
// 处理DO_TRAVERSAL消息
performTraversals();
...
break;
.....
}
}
// 执行遍历
private void performTraversals() {
final View host = mView;
int desiredWindowWidth;
int desiredWindowHeight;
int childWidthMeasureSpec;
int childHeightMeasureSpec;
......
if (mLayoutRequested && !mStopped) {
......
childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
......
// host是一个View对象
host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
......
}
......
}
}
接着上面的measure流程的第五步走下去,以下是android.view.View.java文件中的源码:
public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback,
AccessibilityEventSource {
// 方法是final类型,说明不能被覆写或者重载
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
// 如果有重新请求标志,或者宽高发生改变
if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
widthMeasureSpec != mOldWidthMeasureSpec ||
heightMeasureSpec != mOldHeightMeasureSpec) {
......
// 真正执行测量视图大小操作
// measure ourselves, this should set the measured dimension flag back
onMeasure(widthMeasureSpec, heightMeasureSpec);
......
// 添加重新请求子视图布局标志
mPrivateFlags |= LAYOUT_REQUIRED;
}
......
}
/**
* Call this when something has changed which has invalidated the
* layout of this view. This will schedule a layout pass of the view
* tree.
*/
public void requestLayout() {
if (ViewDebug.TRACE_HIERARCHY) {
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
}
// 添加重新请求布局标志
mPrivateFlags |= FORCE_LAYOUT;
mPrivateFlags |= INVALIDATED;
if (mParent != null) {
if (mLayoutParams != null) {
mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
}
if (!mParent.isLayoutRequested()) {
mParent.requestLayout();
}
}
}
}上面代码的measure流程可以分为4个步骤
1 measure与requestLayout -> 2 onMeasure
紧接着看下android.widget.FrameLayout类的onMeasure总都做了什么?
| 类名.方法名 | 解释 |
| MeasureSpec.getMode(int measureSpec) | 根据提供的测量值(格式)提取模式(上述三个模式之一) |
| MeasureSpec.getSize(int measureSpec) | 根据提供的测量值(格式)提取大小值 |
| MeasureSpec.makeMeasureSpec(int size,int mode) | 根据提供的大小值和模式创建一个测量值(格式) |
| 模式 | 翻译 | 模式与Layout参数对应关系 | 模式描述 |
| UNSPECIFIED | 无限制 | parent view不约束child view的大小 | |
| AT_MOST | 最多的 | wrap_content | child view可以在parent view范围内取值 |
| EXACTLY | 准确的 | fill_parent(例如50dip) | parent view为child view指定固定大小 |
标签:
原文地址:http://blog.csdn.net/androiddevelop/article/details/44263731