Window相关的知识

Activity中层级分为
Activity->PhoneWindow->decorView->[appbar 和 contentView]
其中phoneWindow是window的唯一实现,phoneWindow在activity的attach方法中初始化
Activity的attach是AMS执行到ActivityThread中的handleMessage中执行launchActivity方法调用,执行完attach后会执行Activity的onCreate方法

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
 //....
        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);
//....
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
 }

用户调用setContentView时 按照继承的关系分为两种:
1.继承Activity或者FragmentActivity
直接调用window的setContentView方法

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

在PhoneWindow的伪代码为为

@Override
public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        installDecor();
    }
   //加载app的布局文件
    mLayoutInflater.inflate(layoutResID, mContentParent);
}

第一步是如果mContentParent为空 也就是说deCorView没初始化,执行installDecor

private void installDecor() {
    if (mDecor == null) {
        mDecor = generateDecor();
    }
    if (mContentParent == null) {
        mContentParent = generateLayout(mDecor);
        if (decorContentParent != null) {
            mDecorContentParent = decorContentParent;
        } else {
          //...
        }
}

其中generateDecor是new一个DecorView

protected DecorView generateDecor() {
    return new DecorView(getContext(), -1);
}
//类声明
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker

generateLayout方法主要是对于decorView的属性进行初始化,例如设置标题,图标设置页面样式,
我们代码设置全屏为什么要在setCotentView之前也是这个原因

    if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
        requestFeature(FEATURE_NO_TITLE);
    } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
        // Don't allow an action bar if there is no title.
        requestFeature(FEATURE_ACTION_BAR);
    } 

2.继承AppCompatActivity
是通过一个工厂方法根据编译的系统版本获得对象mDelegate对象
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
setContentView最终会调用AppCompatDelegateImplV7的setContentView方法

@Override
public void setContentView(int resId) {
    ensureSubDecor();
    ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
    contentParent.removeAllViews();
    LayoutInflater.from(mContext).inflate(resId, contentParent);
    mOriginalWindowCallback.onContentChanged();
}

ensureSubDecor方法最终会调用 根据设置加载"subDecor"的布局,和activity的方式不一样没用到decorView

private ViewGroup createSubDecor() {
    TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
    //设置窗口样式
    if (a.getBoolean(R.styleable.Theme_windowNoTitle, false)) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
    } else if (a.getBoolean(R.styleable.Theme_windowActionBar, false)) {
        // Don't allow an action bar if there is no title.
        requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR);
    }
    final LayoutInflater inflater = LayoutInflater.from(mContext);
    ViewGroup subDecor = null;
    if (!mWindowNoTitle) {
        if (mIsFloating) {
            // If we're floating, inflate the dialog title decor
            subDecor = (ViewGroup) inflater.inflate(
                    R.layout.abc_dialog_title_material, null);
            // Floating windows can never have an action bar, reset the flags
            mHasActionBar = mOverlayActionBar = false;
        } else if (mHasActionBar) {
            // Now inflate the view using the themed context and set it as the content view
            subDecor = (ViewGroup) LayoutInflater.from(themedContext)
                    .inflate(R.layout.abc_screen_toolbar, null);

            mDecorContentParent = (DecorContentParent) subDecor
                    .findViewById(R.id.decor_content_parent);
        }
    } else {
        if (mOverlayActionMode) {
            subDecor = (ViewGroup) inflater.inflate(
                    R.layout.abc_screen_simple_overlay_action_mode, null);
        } else {
            subDecor = (ViewGroup) inflater.inflate(R.layout.abc_screen_simple, null);
        }
    // Now set the Window's content view with the decor
    mWindow.setContentView(subDecor);
    return subDecor;
}

WindowaManager在activity的attach中初始化,它自身是个接口类, 继承接口ViewManager,这个三个方法是WindowManager提供给就是activity控制View的

public interface ViewManager
{
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

WindowaManager 实现类是WindowManagerImpl,里面获取WindowManagerGlobal,是具体的方法实现

public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mDisplay, mParentWindow);
    }

    @Override
    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.updateViewLayout(view, params);
    }
    @Override
    public void removeView(View view) {
        mGlobal.removeView(view, false);
    }
}

WindowManager存放三个数组

//存放创建的View
private final ArrayList mViews = new ArrayList();
private final ArrayList mRoots = new ArrayList();
//存放view的属性
private final ArrayList mParams =
        new ArrayList();

你可能感兴趣的:(android开发点滴)