android 怎么让view到最上层,探究 Android View 绘制流程,Activity 的 View 如何展示到屏幕...

本文详细分析了Android中View如何从setContentView(resId)到显示在屏幕上的过程。从Activity的onCreate()方法开始,通过setContentView()将布局加载到DecorView,然后在onResume()时,DecorView与ViewRootImpl关联,最终通过requestLayout()和invalidate()触发绘制流程。内容包括DecorView的生成、布局加载、ViewRootImpl的角色以及绘制流程的关键步骤。
摘要由CSDN通过智能技术生成

基于 Android API 26 Platform 源码

写作背景

在上一篇探究Android View 绘制流程,Xml 文件到 View 对象的转换过程我们了解了setContentView(resId) 如何把 xml 文件转换成 Java 中的 View 对象。本篇文章在此基础上继续探究,View 是如何展示到 Activity 上的。

很多 Android 开发者都知道一个事情

当 Activity 执行 onResume() 方法后,代表 Activity 显示到前台

这句话很短,但是背后隐藏了多少方法的调用呢?下面我们将一层一层的剥开源码寻找真相。

66adb5f52b24

onion.jpg

先从 setContentView(resId) 入手

先说明一下,从 Android 的 Launcher 上点击应用的 Icon 的启动过程比较复杂,本人仍在学习。如果想了解如何启动一个 Activity 的过程可以参考Android Launcher 启动 Activity 的工作过程,这里我们只从关注 Activity 中的 View 显示出来。所以直接从 Activity 的一些方法入手。

在 Activity 的 onCreate(savedInstanceState) 中调用 setContentView(resId),而setContentView(resId)则会调用 PhoneWindow.setContentView(layoutResID)

源码并不是太长

@Override

public void setContentView(int layoutResID) {

// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window

// decor, when theme attributes and the like are crystalized. Do not check the feature

// before this happens.

if (mContentParent == null) {

installDecor();

} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {

mContentParent.removeAllViews();

}

if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {

final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,

getContext());

transitionTo(newScene);

} else {

mLayoutInflater.inflate(layoutResID, mContentParent);

}

mContentParent.requestApplyInsets();

final Callback cb = getCallback();

if (cb != null && !isDestroyed()) {

cb.onContentChanged();

}

}

这里忽略转场动画和一些回调相关的逻辑代码后如下

if (mContentParent == null) {

installDecor();

} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {

mContentParent.removeAllViews();

}

mLayoutInflater.inflate(layoutResID, mContentParent);

mContentParent.requestApplyInsets();

其中 mContentParent 是一个 ViewGroup 引用

private ViewGroup mContentParent;

这样开代码比较简单明了

1. 判断 mContentParent 是否为空,如果为空执行 installDecor()

2. 如果 mContentParent 不为空,清除 mContentParent 的所有子 View

3. 把传入的布局文件转换为 View 对象添加到 mContentParent

分析 installDecor()

然后我们再看下 installDecor() ,因为源码比较长,我们分成几个部分解读

第一部分

if (mDecor == null) {

mDecor = generateDecor();

mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

mDecor.setIsRootNamespace(true);

if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {

mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);

}

}

这几行代码最重要的是调用了方法 generateDecor() 其实就是创建一个 DecorView。这里是不是能想到探究Android View 绘制流程,Canvas 的由来中最后的那张图,我们做个类似的截图截个图

public class MainActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(new TextView(getApplicationContext()));

}

@Override

protected void onResume() {

super.onResume();

}

}

66adb5f52b24

activity_view_01.png

我们看到一个 Activity 页面最底层的 View 就是我们刚看到的 DecorView

第二部分

if (mContentParent == null) {

mContentParent = generateLayout(mDecor);

……

}

这里看到了对 mContentParent 的赋值操作,调用了 generateLayout(mDecor)

protected ViewGroup generateLayout(DecorView decor) {

// Apply data from current theme.

TypedArray a = getWindowStyle();

//设置 Windows Style ,title 、action_bar 、设置键盘弹出方式之类的属性

//……

//……

int layoutResource;

int features = getLocalFeatures();

// System.out.println("Features: 0x" + Integer.toHexString(features));

if ((features &

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值