1.1.1UI绘制流程及原理——View是如何被添加到屏幕窗口上

本片文章讲解:UI绘制流程-源码讲解(基于API28的源码分析)

文章大纲:

part1:View是如何被添加到屏幕窗口上

part2:View的绘制流程

本片先讲part1:View是如何被添加到屏幕窗口上,part2:放在下一篇文章讲解。

 

part1:View是如何被添加到屏幕窗口上

首先,MainActivity中调用了setContentView(R.layout.activity_main);方法,我们跟进去,来到了Activity的源码当中:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback{
    //省略....
    /**
     * Set the activity content from a layout resource.  The resource will be
     * inflated, adding all top-level views to the activity.
     *
     * @param layoutResID Resource ID to be inflated.
     *
     * @see #setContentView(android.view.View)
     * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
     */
    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }
    //省略....
}

其中getWindow()方法返回了Window对象:

class Activity{
    /**
     * Retrieve the current {@link android.view.Window} for the activity.
     * This can be used to directly access parts of the Window API that
     * are not available through Activity/Screen.
     *
     * @return Window The current window, or null if the activity is not
     *         visual.
     */
    public Window getWindow() {
        return mWindow;
    }
}

继续查找Window这个类,发现类注释上面有这样一段话:

/**
 * Abstract base class for a top-level window look and behavior policy.  An
 * instance of this class should be used as the top-level view added to the
 * window manager. It provides standard UI policies such as a background, title
 * area, default key processing, etc.
 *
 * <p>The only existing implementation of this abstract class is
 * android.view.PhoneWindow, which you should instantiate when needing a
 * Window.
 */
public abstract class Window {

    //...
}

The only existing implementation of this abstract class is android.view.PhoneWindow,也就是说PhoneWindow是Window类的唯一继承实现。那么我们可以找到PhoneWindow类的setContentView方法了:

public class PhoneWindow extends Window implements MenuBuilder.Callback {

    //....

    @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类中有两个比较重要的方法installDecor()和mLayoutInflater.inflate(layoutResID, mContentParent)。接下来我们分别说一下这个两个方法的作用:

installDecor方法:

class PhoneWinow{

    private void installDecor() {
        if (mDecor == null) {
            mDecor = generateDecor();//注意这里 方法①
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);//注意这里 方法②
        }
    }

}

这里先提一句,就是在installDecor方法里面有一个mContentParent = generateLayout(mDecor);这里给mContentParent赋值之后,回到setContentView方法中也有一个mContentParent对象,调用的方法为 mLayoutInflater.inflate(layoutResID, mContentParent),这两个mContentParent是同一个对象。

 

然后我们跟进到generateDecor方法里面:

class PhoneWindow{
    protected DecorView generateDecor(int featureId) {
        // System process doesn't have application context and in that case we need to directly use
        // the context we have. Otherwise we want the application context, so we don't cling to the
        // activity.
        Context context;
        if (mUseDecorContext) {
            Context applicationContext = getContext().getApplicationContext();
            if (applicationContext == null) {
                context = getContext();
            } else {
                context = new DecorContext(applicationContext, getContext());
                if (mTheme != -1) {
                    context.setTheme(mTheme);
                }
            }
        } else {
            context = getContext();
        }
        return new DecorView(context, featu
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值