setContentView中的源码探索(未修订)

setContentView中的源码探索(未修订)

  • PhoneWindow是window的子类
  • DecorView是整个ViewTree的最顶层View
  • DecorView和加载了我们提供的布局
  • ViewRootImpl则负责渲染视图,WindowManager和DecorView的纽带

基于android 25源码进行探索,先从setContentView中进行探索

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

    public Window getWindow() {
        return mWindow;
    }

    private Window mWindow;

可以看到主要是从getwindow调用的方法,而getWindow就直接返回了一个window,可以看出window就是一个抽象类,我们的找出真正的实现类,用AS搜索了一下,看到在attach方法中找了实现类

 final void attach(...) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
      ...
    mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
    }

PhoneWindow就是window的实现类,接着我们就重点讲解这里,因为就是这里把我们的View给填充进入了

    public PhoneWindow(Context context, Window preservedWindow) {
        this(context);
 ...
        if (preservedWindow != null) {
            mDecor = (DecorView) preservedWindow.getDecorView();
            mElevation = preservedWindow.getElevation();
       ...
        }
...
    }

    public final View getDecorView() {
        if (mDecor == null || mForceDecorInstall) {
            installDecor();
        }
        return mDecor;
    }



   private void installDecor() {

        if (mDecor == null) {
            mDecor = generateDecor(-1);

        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

            final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
                    R.id.decor_content_parent);

            if (decorContentParent != null) {
                mDecorContentParent = decorContentParent;
                mDecorContentParent.setWindowCallback(getCallback());
                if (mDecorContentParent.getTitle() == null) {
                    mDecorContentParent.setWindowTitle(mTitle);
                }


            } else {
                mTitleView = (TextView) findViewById(R.id.title);
                if (mTitleView != null) {
                    if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                        final View titleContainer = findViewById(R.id.title_container);
                        if (titleContainer != null) {
                            titleContainer.setVisibility(View.GONE);
                        } else {
                            mTitleView.setVisibility(View.GONE);
                        }
                        mContentParent.setForeground(null);
                    } else {
                        mTitleView.setText(mTitle);
                    }
                }
            }

            if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
                mDecor.setBackgroundFallback(mBackgroundFallbackResource);
            }


    }

PhoneWindow构造方法创建了DecorView,而我前面所说DecorView是整个ViewTree的最顶层View,installDecor中也设置了标题栏和内容

generateDecor
  protected DecorView generateDecor(int featureId) {
      ...
        return new DecorView(context, featureId, this, getAttributes());
    }

我们在看看具体是怎么填充我们提供的View的

generateLayout
  protected ViewGroup generateLayout(DecorView decor) {

        ...
       mDecor.startChanging();
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
        ...
  }

void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {

        mDecorCaptionView = createDecorCaptionView(inflater);
        //加载layoutResource
        final View root = inflater.inflate(layoutResource, null);
        if (mDecorCaptionView != null) {
            if (mDecorCaptionView.getParent() == null) {
                addView(mDecorCaptionView,
                        new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
            }
            mDecorCaptionView.addView(root,
                    new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));
        } else {

            // Put it below the color views.
            addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        }
        mContentRoot = (ViewGroup) root;
        initializeElevation();
    }

从generateLayout中的onResourcesLoaded方法中,终于看到了我们想看到的东西。

到目前为止,通过setContentView方法,创建了DecorView和加载了我们提供的布局,但是我们并没有被window添加

Window添加DecorView

每一个Activity组件都有一个关联的Window对象,用来描述一个应用程序窗口。每一个应用程序窗口内部又包含有一个View对象,用来描述应用程序窗口的视图。

首先,在ActivityThread#handleLaunchActivity中启动Activity,在这里面会调用到Activity#onCreate方法,从而完成上面所述的DecorView创建动作,当onCreate()方法执行完毕,在handleLaunchActivity方法会继续调用到ActivityThread#handleResumeActivity方法,我们看看这个方法的源码:

  final void handleResumeActivity(...) {
      ...
        //这里会调用到onResume()方法
        r = performResumeActivity(token, clearHide, reason);

            ...
                final Activity a = r.activity;
                r.window = r.activity.getWindow();// 获得window对象
                View decor = r.window.getDecorView();// 获得DecorView对象
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager(); // 获得windowManager对象
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;

                if (a.mVisibleFromClient && !a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);// 调用addView方法
                }


        }
    }

就在这个方法里,终于看到windowManager将decorView添加进去了,当你准备点进去看addView 方法时,你没猜错它(ViewManager)又TM是抽象或者接口…windowManager都是抽象类,那到底谁实现了他呢…
还记得我为啥说每一个Activity组件都有一个关联的Window对象,请回到我上面说的activity->attach

//设置WindowManager
  mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

   public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
      ...
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

看到这里知道是谁了吧,就是他 WindowManagerImpl,赶紧看看他的addView方法中写了啥

WindowManagerImpl->addView
   @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

  public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {

        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;

        //创建ViewRootImpl
            root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
        //ViewRootImpl.setView
            root.setView(view, wparams, panelParentView);


    }

ViewRootImpl#setView方法,并把DecorView作为参数传递进去,在这个方法内部,会通过跨进程的方式向WMS(WindowManagerService)发起一个调用,从而将DecorView最终添加到Window上,在这个过程中,ViewRootImpl、DecorView和WMS会彼此关联,至于详细过程这里不展开来说了

ViewRootImpl对他不熟悉的可以看看 Android中的ViewRootImpl类源码解析

参考Android View源码解读:浅谈DecorView与ViewRootImpl

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值