View的创建过程

本文详细阐述了Android中Activity启动时View的创建过程,从ActivityThread.handleLaunchActivity开始,逐步解析Activity创建、setContentView、PhoneWindow安装DecorView直至ViewRoot的建立。每个步骤都深入到相关函数的调用与作用,揭示了UI界面如何从无到有呈现的过程。
摘要由CSDN通过智能技术生成

每一个Activity组件都有一个关联的Window对象,用来描述一个应用程序窗口。每一个应用程序窗口内部又包含有一个View对象,用来描述应用程序窗口的视图。应用程序窗口视图是真正用来实现UI内容和布局的,也就是说,每一个Activity组件的UI内容和布局都是通过与其所关联的一个Window对象的内部的一个View对象来实现的。

应用程序窗口内部所包含的视图对象的实际类型为DecorView。DecorView类继承了View类,是作为容器(ViewGroup)来使用的,它的实现如图所示:
在这里插入图片描述

每一个应用程序窗口的视图对象都有一个关联的ViewRoot对象,这些关联关系是由窗口管理器来维护的,如图所示:
在这里插入图片描述
简单来说,ViewRoot相当于是MVC模型中的Controller,它有以下职责:

  1. 负责为应用程序窗口视图创建Surface。
  2. 配合WindowManagerService来管理系统的应用程序窗口。
  3. 负责管理、布局和渲染应用程序窗口视图的UI。

那么,应用程序窗口的视图对象及其所关联的ViewRoot对象是什么时候开始创建的呢? Activity组件在启动的时候,系统会为它创建窗口对象(Window),同时,系统也会为这个窗口对象创建视图对象。另一方面,当Activity组件被激活的时候,系统如果发现与它的应用程序窗口视图对象所关联的ViewRoot对象还没有创建,那么就会先创建这个ViewRoot对象,以便接下来可以将它的UI渲染出来。

Activity组件在启动的过程中,会调用ActivityThread类的成员函数handleLaunchActivity,用来创建以及首次激活Activity组件,因此,接下来我们就从这个函数开始,具体分析应用程序窗口的视图对象及其所关联的ViewRoot对象的创建过程。
在这里插入图片描述

Step 1. ActivityThread.handleLaunchActivity

public final class ActivityThread {
     
    ......  
  
    private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
     
        ......  
  
        Activity a = performLaunchActivity(r, customIntent);  
  
        if (a != null) {
     
            ......  
  
            handleResumeActivity(r.token, false, r.isForward);  
  
            ......  
        }  
  
        ......  
    }  
  
    ......  
}  

函数首先调用ActivityThread类的成员函数performLaunchActivity来创建要启动的Activity组件。在创建Activity组件的过程中,还会为该Activity组件创建窗口对象和视图对象。Activity组件创建完成之后,就可以将它激活起来了,这是通过调用ActivityThread类的成员函数handleResumeActivity来执行的。


Step 2. ActivityThread.performLaunchActivity

它主要就是创建一个Activity组件实例,并且调用这个Activity组件实例的成员函数onCreate来让其执行一些自定义的初始化工作。


Step 3. Activity.onCreate

我们在实现一个Activity组件的时候,也就是在实现一个Activity子类的时候,一般都会重写成员函数onCreate,以便可以执行一些自定义的初始化工作,其中就包含初始化UI的工作。

public class Hello extends Activity implements OnClickListener {
       
    ......    
        
    /** Called when the activity is first created. */    
    @Override    
    public void onCreate(Bundle savedInstanceState) {
       
        super.onCreate(savedInstanceState);    
        setContentView(R.layout.main);    
    
        ......    
    }    
  
    ......  
}  

其中,调用从父类Activity继承下来的成员函数setContentView就是用来创建应用程序窗口视图对象的。


Step 4. Activity.setContentView

public class Activity extends ContextThemeWrapper  
        implements LayoutInflater.Factory,  
        Window.Callback, KeyEvent.Callback,  
        OnCreateContextMenuListener, ComponentCallbacks {
     
    ......  
  
    private Window mWindow;  
    ......  
  
    public Window getWindow() {
     
        return mWindow;  
    }  
    ......  
  
    public void setContentView(int layoutResID) {
     
        getWindow().setContentView(layoutResID);  
    }  
  
    ......  
} 

首先调用另外一个成员函数getWindow来获得成员变量mWindow所描述的一个窗口对象,接着再调用这个窗口对象的成员函数setContentView来执行创建应用程序窗口视图对象的工作。mWindow指向的是一个PhoneWindow对象。


Step 5. PhoneWindow.setContentView

public class PhoneWindow extends Window implements MenuBuilder.Callback {
     
    ......  
  
    // This is the view in which the window contents are placed. It is either  
    // mDecor itself, or a child of mDecor where the contents go.  
    private ViewGroup mContentParent;  
    ......  
  
    @Override  
    public void setContentView(int layoutResID) {
     
        if (mContentParent == null) {
     
            installDecor();  
        } else {
     
            mContentParent.removeAllViews();  
        }  
        mLayoutInflater.inflate(layoutResID, mContentParent);  
        final Callback cb = getCallback();  
        if (cb != null) {
     
            cb.onContentChanged();  
        }  
    }  
  
    ......  
}

PhoneWindow类的成员变量mContentParent用来描述一个类型为DecorView的视图对象,或者这个类型为DecorView的视图对象的一个子视图对象,用作UI容器。当它的值等于null的时候,就说明正在处理的应用程序窗口的视图对象还没有创建。在这种情况下,就会调用成员函数installDecor来创建应用程序窗口视图对象。否则的话,就说明是要重新设置应用程序窗口的视图。在重新设置之前,首先调用成员变量mContentParent所描述的一个ViewGroup对象来移除原来的UI内空。

由于我们是在Activity组件启动的过程中创建应用程序窗口视图的,因此,我们就假设此时PhoneWindow类的成员变量mContentParent的值等于null。接下来,函数就会调用成员函数installDecor来创建应用程序窗口视图对象,接着再通过调用PhoneWindow类的成员变量mLayoutInflater所描述的一个LayoutInflater对象的成员函数inflate来将参数layoutResID所描述的一个UI布局设置到前面所创建的应用程序窗口视图中去,最后还会调用一个Callback接口的成员函数onContentChanged来通知对应的Activity组件,它的视图内容发生改变了。<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值