文章目录
- 1. 探讨 Android 的 View 显示过程
- 1.1. `onFinishInflate`
- 1.2. `onAttachedToWindow`
- 1.3. `onMeasure`
- 1.4. `onSizeChanged`
- 1.5. `onLayout`
- 1.6. `onDraw`
- 2. 系统代码分析
- 1.1. `onFinishInflate`
- 1.2. `onAttachedToWindow`
- 1.3. `onMeasure`
- 1.4. `onSizeChanged`
- 1.5. `onLayout`
- 1.6. `onDraw`
- 3. 视图显示过程总结
- 4. 优化和性能考虑
- 5. 结论
- 6. 进一步深入探讨 Android 的 View 显示过程
- 6.1. `onFinishInflate`
- 6.2. `onAttachedToWindow`
- 6.3. `onMeasure`
- 6.4. `onSizeChanged`
- 6.5. `onLayout`
- 6.6. `onDraw`
- 7. 视图显示过程总结(续)
1. 探讨 Android 的 View 显示过程
在 Android 中,View 的显示过程涉及多个步骤和方法,从底层到上层依次执行。理解这些步骤和方法对优化 UI 性能和实现复杂的自定义 View 非常重要。
1.1. onFinishInflate
当一个 View 从 XML 布局文件中被加载并完成所有子 View 的初始化时,onFinishInflate
方法被调用。这个方法在整个布局层次结构被完全创建之后调用,可以在这里进行一些额外的初始化工作。
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// 视图和子视图的初始化工作
}
1.2. onAttachedToWindow
当一个 View 被附加到一个窗口时,onAttachedToWindow
方法被调用。在这个方法中,可以进行一些与窗口相关的初始化工作,例如启动动画、设置监听器等。
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
// 视图附加到窗口后的操作
}
1.3. onMeasure
onMeasure
方法用于测量 View 的大小。这个方法在布局过程中多次调用,用于确定每个 View 的宽度和高度。自定义 View 时,通常需要重写这个方法以处理特定的测量需求。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
1.4. onSizeChanged
当 View 的大小发生变化时,onSizeChanged
方法被调用。这通常发生在 View 的初次布局和大小调整时。在这个方法中,可以根据新的大小进行调整。
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 视图大小改变后的操作
}
1.5. onLayout
onLayout
方法用于为 View 的所有子 View 安置位置。这个方法在布局过程中调用,用于确定子 View 的位置。
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// 布局子视图的位置
int childLeft = 0;
int childTop = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight());
childTop += child.getMeasuredHeight();
}
}
1.6. onDraw
onDraw
方法用于绘制 View 的内容。在这个方法中,可以使用 Canvas
对象进行绘制操作,例如绘制文本、图形等。自定义 View 时,通常需要重写这个方法以实现特定的绘制需求。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 自定义绘制操作
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
}
2. 系统代码分析
1.1. onFinishInflate
在 ViewGroup
类中,当所有的子 View 都被加载并添加到父 View 时,onFinishInflate
方法被调用。它确保了布局的完整性和一致性。
1.2. onAttachedToWindow
onAttachedToWindow
方法在 View 的 ViewRootImpl
被创建并与窗口关联时调用。它确保 View 可以访问窗口相关的资源和服务。
1.3. onMeasure
onMeasure
方法是 View
类中的一个核心方法,它通过 MeasureSpec
参数来计算 View 的大小。MeasureSpec
包含测量模式和尺寸信息。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// 自定义测量逻辑
}
1.4. onSizeChanged
onSizeChanged
方法在 View
类中实现,用于处理 View 大小的变化。它提供了新旧尺寸的信息,以便在大小变化时进行相应的调整。
1.5. onLayout
onLayout
方法在 ViewGroup
类中实现,用于布置子 View 的位置。它通过遍历子 View 并调用每个子 View 的 layout
方法来实现布局。
1.6. onDraw
onDraw
方法在 View
类中实现,用于绘制 View 的内容。Canvas
对象提供了一系列绘制方法,可以在 onDraw
方法中调用这些方法进行自定义绘制。
3. 视图显示过程总结
-
视图加载和初始化:
- XML 布局文件被解析并创建 View 实例。
onFinishInflate
方法被调用,完成视图和子视图的初始化。
-
视图附加到窗口:
- 当 View 被添加到窗口时,
onAttachedToWindow
方法被调用。 - 可以在此方法中进行与窗口相关的初始化工作。
- 当 View 被添加到窗口时,
-
测量视图:
- 在布局过程中,
onMeasure
方法被调用,用于测量 View 的大小。 - 通过
MeasureSpec
参数来确定 View 的测量模式和尺寸。
- 在布局过程中,
-
视图大小变化:
- 当 View 的大小发生变化时,
onSizeChanged
方法被调用。 - 可以在此方法中根据新的大小进行调整。
- 当 View 的大小发生变化时,
-
布局子视图:
- 在布局过程中,
onLayout
方法被调用,用于布置子 View 的位置。 - 通过遍历子 View 并调用每个子 View 的
layout
方法来实现布局。
- 在布局过程中,
-
绘制视图:
- 在绘制过程中,
onDraw
方法被调用,用于绘制 View 的内容。 - 可以在
onDraw
方法中使用Canvas
对象进行自定义绘制。
- 在绘制过程中,
4. 优化和性能考虑
- 视图层次结构优化:避免过深的视图层次结构,尽量减少布局嵌套。
- 异步任务:避免在主线程中执行耗时操作,使用异步任务处理。
- 内存管理:及时释放不再需要的资源,避免内存泄漏。
5. 结论
通过深入理解和合理使用 Android 中的 View
显示过程,可以构建出高效、稳定且用户体验良好的应用程序。掌握这些关键技术和设计模式,不仅可以提高开发效率,还能显著提升应用的整体质量。在实际开发中,灵活应用这些技术,结合实际需求进行优化和调整,是构建优秀 Android 应用的基础。
6. 进一步深入探讨 Android 的 View 显示过程
为了更好地理解 Android View 的显示过程,我们需要深入分析系统源码中的具体实现。以下是一些关键方法在系统源码中的详细说明。
6.1. onFinishInflate
在 ViewGroup.java
中,onFinishInflate
方法的定义如下:
protected void onFinishInflate() {
// This is called after a view and all of its children has been inflated
}
这个方法被调用时,整个布局树已经被完全构建,可以在此处进行一些额外的初始化工作。
6.2. onAttachedToWindow
在 View.java
中,onAttachedToWindow
方法的定义如下:
protected void onAttachedToWindow() {
mAttachInfo = mParent.getViewRootImpl().mAttachInfo;
if (mOverlay != null) {
mOverlay.getOverlayView().dispatchAttachedToWindow(mAttachInfo, mWindowAttachCount);
}
onVisibilityAggregated(isAggregatedVisible());
if ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
refreshDrawableState();
}
// Additional operations when the view is attached to the window
}
这个方法确保了 View 能够访问与窗口相关的资源和服务。
6.3. onMeasure
onMeasure
方法在 View.java
中的实现如下:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// Measure the view dimensions
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
// Measure the width based on the content and padding
width = computeWidth();
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
// Measure the height based on the content and padding
height = computeHeight();
}
setMeasuredDimension(width, height);
}
onMeasure
方法通过 MeasureSpec
参数确定 View 的测量模式和尺寸。
6.4. onSizeChanged
onSizeChanged
方法在 View.java
中的实现如下:
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// Handle the size change
if (w != oldw || h != oldh) {
// Perform any operations needed when the size changes
}
}
这个方法提供了新旧尺寸的信息,以便在大小变化时进行相应的调整。
6.5. onLayout
onLayout
方法在 ViewGroup.java
中的实现如下:
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
int childLeft = // Calculate the child's left position
int childTop = // Calculate the child's top position
child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight());
}
}
}
onLayout
方法遍历子 View 并调用每个子 View 的 layout
方法来实现布局。
6.6. onDraw
onDraw
方法在 View.java
中的实现如下:
protected void onDraw(Canvas canvas) {
// Perform custom drawing operations
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
}
onDraw
方法使用 Canvas
对象进行自定义绘制。
7. 视图显示过程总结(续)
-
视图加载和初始化:
- 解析 XML 布局文件并创建 View 实例。
- 调用
onFinishInflate
方法,完成视图和子视图的初始化。
-
视图附加到窗口:
- View 被添加到窗口时调用
onAttachedToWindow
方法。 - 进行与窗口相关的初始化工作。
- View 被添加到窗口时调用
-
测量视图:
- 布局过程中调用
onMeasure
方法测量 View 的大小。 - 使用
MeasureSpec
参数确定测量模式和尺寸。
- 布局过程中调用
-
视图大小变化:
- View 大小变化时调用
onSizeChanged
方法。 - 根据新的大小进行调整。
- View 大小变化时调用
-
布局子视图:
- 布局过程中调用
onLayout
方法布置子 View 的位置。 - 遍历子 View 并调用每个子 View 的
layout
方法实现布局。
- 布局过程中调用
-
绘制视图:
- 绘制过程中调用
onDraw
方法绘制 View 的内容。 - 使用
Canvas
对象进行自定义绘制。
- 绘制过程中调用
欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力 |