View工作原理及源码分析

一些基本概念

Window

  • 定义:Window是一个抽象概念,代表一个窗口,它负责界面的展示以及交互。在Android中,Window的具体实现类是PhoneWindow。
  • 功能:Window内部持有一个DecorView作为视图的根布局,并通过WindowManager将DecorView加载到窗口中。它还负责处理与窗口相关的各种事件,如窗口大小变化、焦点变化等。

Activity

  • 定义:Activity是Android四大组件之一,负责界面展示、用户交互与业务逻辑处理。
  • 功能:Activity内部维护着一个Window对象,通过该Window对象来管理视图的添加、布局、绘制等工作。Activity通过调用setContentView()方法将布局资源添加到Window的内容视图中。此外,Activity还负责处理生命周期事件,如创建、暂停、恢复和销毁等。

View

  • 定义:View是Android用户界面基本构建块之一,是各种UI组件的基类。
  • 功能:View负责显示应用程序中的内容和与用户进行交互。它通常被放置在Window容器中,由Window进行管理和展示。View具有自己的属性、样式和行为,并可以包含其他View或ViewGroup来构建复杂的用户界面。

WindowManager

  • 定义:WindowManager是一个接口,用于管理窗口的添加、删除和更新等操作。
  • 功能:WindowManager的具体实现类是WindowManagerImpl,它内部将所有的方法调用转交给WindowManagerGlobal来处理。WindowManagerGlobal通过调用ViewRootImpl来完成对View的操作。WindowManager还负责处理与窗口相关的各种事件,如窗口大小变化、焦点变化等,并将这些事件传递给相应的Window进行处理。

ViewRootImpl

  • 定义:ViewRootImpl是视图层次结构的顶部,它实现了View与WindowManager之间所需要的协议。
  • 功能:ViewRootImpl负责将View和布局参数添加到屏幕上,并控制View的测量、布局和绘制过程。它还负责处理与View相关的事件,如触摸事件、按键事件等,并将这些事件传递给相应的View进行处理。此外,ViewRootImpl还通过IWindowSession接口与WindowManagerService进行通信,以实现对窗口的管理和更新。

在这里插入图片描述

关系总结

  • Window与Activity:Activity内部持有一个Window对象,通过该Window对象来管理视图和界面展示。Window作为Activity的下属或视图的管理者,负责处理与窗口相关的各种事件。
  • Window与View:Window是视图的承载器,内部持有一个DecorView作为视图的根布局。View被放置在Window容器中,由Window进行管理和展示。
  • Activity与View:Activity通过setContentView()方法将布局资源(由View和ViewGroup组成)添加到Window的内容视图中。用户与Android应用的交互主要是通过View进行的,这些事件会被View捕获并传递给Activity进行处理。
  • WindowManager与Window/View:WindowManager负责管理窗口的添加、删除和更新等操作。它通过WindowManagerImpl和WindowManagerGlobal来实现对Window和View的管理。WindowManager还负责处理与窗口相关的各种事件,并将这些事件传递给相应的Window进行处理。
  • ViewRootImpl与Window/View:ViewRootImpl是视图层次结构的顶部,它实现了View与WindowManager之间所需要的协议。它负责将View和布局参数添加到屏幕上,并控制View的测量、布局和绘制过程。ViewRootImpl还与WindowManagerService进行通信,以实现对窗口的管理和更新。

View Three的创建过程

流程

列子:用户启动一个界面。

  • 经过一系列后AMS会通知应用启动一个Activity的,最终将到ActivityThread所管理的LAUNCH_ACTIVITY消息,执行handleLaunchActivity()。
  • 创建Activity对象和Window对象。
  • 创建DecorView,加载页面内容布局到DecorView上,形成View树。
  • 需要将View添加到本地的WindowManagerGlobal中,最终注册到WMS中。

源码(以下源码分析基于7.1和8.0)

在这里插入图片描述

handleLaunchActivity
/*frameworks/base/core/java/android/app/ActivityThread.java*/
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
   
...
    Activity a = performLaunchActivity(r, customIntent);//启动Activity
    if (a != null) {
   
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed,r.lastProcessedSeq, reason);//resume当前Activity
    }
}
  • performLaunchActivity()生成一个Activity对象,且执行Activity的attach(),通过callActivityOnCreate()间接调用Activity.onCreate()。Activity的attach()主要是对内部一些变量赋值,如mWindow。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
   
    Activity activity = null;
    try {
   
         java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
         activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);//加载创建这个Activity
         ...
        } catch (Exception e) {
   
          ...
        }
    try {
   
            Application app = r.packageInfo.makeApplication(false,mInstrumentation);
            ...
            if (activity != null) {
   
                activity.attach(appContext, this, getInstrumentation(),  r.token,
                r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window);
                ...
                if (r.isPersistable()) {
   
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
   
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
            }
            ...
        } catch (Exception e) {
   
          ...
        }
}
  • Activity.onCreate()里会执行setContentView()生成DecorView,setContentView()最终是调用到Window.java的实现类PhoneWindow。
/*frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java*/
public void setContentView(int layoutResID) {
   
        if (mContentParent == null) {
   //首次加载这个函数的情况
            installDecor();//先生成mDecor
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
   
            mContentParent.removeAllViews();//否则移除旧的view
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
   
            ...
        } else {
   
            mLayoutInflater.inflate(layoutResID, mContentParent);//根据资源ID创建View,
        }
        ...
    }
    private void installDecor() {
   
        mForceDecorInstall = false;
        if (mDecor == null) {
   
            //创建一个DecorView
            mDecor = generateDecor(-1);
            ...
        }
        if (mContentParent == null) {
   
            mContentParent = generateLayout(mDecor);
        }
   }
  • 取出Window样式。
  • 根据layoutResource指定的layout(即xml)文件,来inflate出对应的View,将View添加到DecorView中。
  • DecorView包含两部分内容,一个是通过setContentView实际要显示的视图,另外一个是系统的视图如Title,ActionBar等。
    protected ViewGroup generateLayout(DecorView decor) {
   
        TypedArray a = getWindowStyle();//获取窗口样式
        //根据具体的样式为layoutResource设置匹配的资源
        int layoutResource;
        int features = getLocalFeatures();
        // System.out.println("Features: 0x" + Integer.toHexString(features));
        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
   
            layoutResource = R.layout.screen_swipe_dismiss;
            setCloseOnSwipeEnabled(true);
        } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
   
        }
        ...
         final View root = inflater.inflate(layoutResource, null);
         mDecor.addView(root,new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));
                  ViewGro
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值