Android 6.0 View加载流程源码分析

上一篇文章根据源码分析了下Android的App启动的整个流程,那么App启动起来之后,是需要和用户交互的,所以,界面的显示内容是极其重要的一部分。然而大家都知道,Android的UI基本上都是附属在Acticity上的,那么接下来就分析一下,Activity启动后,视图是如何加载出来的。

Window

在开始分析视图创建之前,首先让我们先了解一下Window。相信大家之前应该遇见过这个类。但是实际开发中却很少能直接接触到Window。其实我们可以顾名思义,可以把Window 看成是Activity 或者ToastDialog 的窗口。就是这写组件需要展示的内容,都会附属到Window上。然而,Window 是一个抽象类,其具体的实现类是PhoneWindow。那么下面我们要分析Activity的视图创建,很显然首先需要创建Window,比较Activity 的视图是需要附属到Window上的。

Window的创建

Window是在哪里被创建的呢?还记得 Android 6.0 View加载流程源码分析 中讲到的performLaunchActivity这个方法吗,没错就是从这里开始的。在这里面,当Activity被创建之后,会调用其attach 方法。其里面有如下一段代码:

mWindow = new PhoneWindow(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);         mWindow.getLayoutInflater().setPrivateFactory(this);

首先直接new 了一个Window 的实现类PhoneWindow对象,然后为其设置Callback接口回调。因为Activity 实现了WindowCallbackOnWindowDismissedCallback接口,所以这里都直接传入了当前的Activity。这个Callback里面有一系列事件的回调方法,这里面有我们熟悉dispatchTouchEventdispatchKeyEvent等等的方法。到此,Avtivity 中的 Window 对象算是创建成功了。

既然Window已经创建了,那么我们的View如何附属到Window 上呢?其实是通过WindowManageraddView方法。但是这里我们的视图还没创建呢,就先分析完视图的创建吧。

视图创建

对于视图的创建又该从何开始呢?这个方法其实每一个Android开发者都再熟悉不过了。setContentView!嗯,就是从这里开始,下面是这个方法的源码。

    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

看到了吧,这里又调用了之前在attach方法中创建好的Window对象的setContentView方法。进去看看。

    @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();
        }
    }

当然这个是PhoneWindow里面的方法,原因上面已经说到了,Activity里面创建的就是PhoneWindow的对象。然后我们看代码。一进去首先判断mContentParent是否为空。这个mContentParent其实是DecorView 里面的内容区域其实就是一个FrameLayout相信大家了解这方面的只是,不了解的可以自行谷歌。网上有很多说明setContentView为何不叫setView的文章。嗯,其实这里的mContentParent肯定为空的,如果是第一次加载视图的话。那么就会进入installDecor方法。这个方法完成了两件事,调用generateDecor方法创建了DecorView。然后在generateLayout方法里面创建了上面说到 的mContentParent

View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值