简述Activity的启动流程(界面显示)

写完上一篇博客之后,花时间看了一下Binder,还是只能看个皮毛,所以,在自己没有完全掌握的情况的,我会更注重这种上层的宏观流程,而不纠结于底层细节。
我们自己写的布局是在setContentView()中开始执行的,大致流程就是,系统会根据主题什么的创建出一个最外层的ViewGroup,然后把我们的View添加进去,然后通知WmS添加ViewGroup,界面就这么出来了。
Activity的attach()方法

 mWindow = PolicyManager.makeNewWindow(this);

mWindow是一个PhoneWindow对象,该Window和Activity进行了绑定。
PhoneWindow

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
    ......
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mContentParent.addView(view, params);
  ......

DecorView是一个最外层布局,看一看generateLayout()方法

        ......
        View in = mLayoutInflater.inflate(layoutResource, null);
        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        ......

in就是系统根据主题什么的创建出来的一个外层布局,并且给了我们一个id为
ID_ANDROID_CONTENT的父布局,我们将自己给Activity设置的View就添加到这个父布局中。
此时,我们已经将本地工作准备完毕,接着就是告知WmS将这个ViewGroup显示出来。
当我们向系统发出启动Activity的消息之后,系统经过处理之后也会回发一个消息给我们,这个消息被ApplicationThread接收,然后发一个handler消息给ActivityThread,然后执行handleLaunchActivity()

            .......
 Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
            ......

我们都知道,Activity的onResume()方法执行表示界面已经显示出来了

handleResumeActivity()方法

 if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                      }
    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

在这个方法中就是请求WmS将View添加进去。
wm.addView最终执行的是WindowManagerGlobal(全局唯一)

root = new ViewRootImpl(view.getContext(), display);
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
        }
        // do this last because it fires off messages to start doing things
        try {
        //这个方法很重要
            root.setView(view, wparams, panelParentView);

ViewRootImpl的setView()方法

   res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mInputChannel);

这里的mWindow是一个W类,也是ViewRootImpl的内部类,当WmS那边添加完窗口后,会反馈一个消息,这个消息由W类接受,然后W类发送一个Handler消息给ViewRootImpl。

说到这里,有必要理清一下WindowManger,到底有几个,我们拿到的是哪个,举个例子吧,Toast与Activity是无关的吧,原因就在WindowManager身上。
先看看Activity是怎么拿的吧

    @Override
    public Object getSystemService(String name) {
    ......
        if (WINDOW_SERVICE.equals(name)) {
            return mWindowManager;
        } else if (SEARCH_SERVICE.equals(name)) {
            ensureSearchManager();
            return mSearchManager;
        }
        return super.getSystemService(name);
    }

返回的是与他绑定的Window的WindowManager.
ActivityThread的performLaunchActivity()方法:

//此时Activity对象已经创建出来
......
 if (activity != null) {
 //为Activity创建一个ContextImpl对象
                Context appContext = createBaseContextForActivity(r, activity);
                //配置Activity内部的参数
                  activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config);

再看Activity的attach()方法

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

ContextImpl有一段静态代码块

 static {
        ......
        //这里有一堆类似的XXX_SERVICE的注册
        ......
        registerService(WINDOW_SERVICE, new ServiceFetcher() {
                Display mDefaultDisplay;
                public Object getService(ContextImpl ctx) {
                    //搞一个Display实例
                    Display display = ctx.mDisplay;
                    if (display == null) {
                        if (mDefaultDisplay == null) {
                            DisplayManager dm = (DisplayManager)ctx.getOuterContext().
                                    getSystemService(Context.DISPLAY_SERVICE);
                            mDefaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
                        }
                        display = mDefaultDisplay;
                    }
                    //返回一个WindowManagerImpl实例
                    return new WindowManagerImpl(display);
                }});
        ......
    }

一旦执行注册,就放到缓存中了,下次你请求拿的时候就是从缓存队列中拿到的,所以,他们是全局唯一的。我们通过Activity的getSystemService()拿到的就是这里的WindowManager.
再回到Activity的onAttach()方法中的那个setWindowManager()方法

    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {

        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        //通过全局的WindowManager创建一个本地的(属于Activity)
        //的localWindowManager
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }
 public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
 //这个parentWindow就是与Activity绑定的Window
        return new WindowManagerImpl(mDisplay, parentWindow);
    }

注意:在注册服务的代码中,这个parentWindow==null.

你可能感兴趣的:(Activity启动)