Activity、View、Window和WindowManager

本文深入解析了Android系统中Window的工作原理及其与WindowManager的关系。从Window的创建到视图的加载,再到Activity生命周期中关键方法的调用流程,全面阐述了Window如何管理和呈现视图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Window简介


(1)Window表示一个窗口的概念,一般用不到,当在某些特殊的时候我们需要在桌面上显示一个类似悬浮窗的东西就需要Window来实现。
(2)Window是一个抽象类,它的具体实现是PhoneWindow。
(3)创建一个Window只需要通过WindowManager即可完成。
(4)WindowManager是外界访问Window的入口,Window的具体实现是WindowManagerService,WindowManager和WindowManagerService的交互是一个IPC过程。
(5)Android中所有的视图都是通过Window呈现的,不管是Activity、Dialog还是Toast,他们的视图实际上都是附加在Window上的,因此Window实际是View的直接管理者。

二、Window和WindowManager

根据Activity的生命周期函数来理解上述控件的初始化过程:

ActivityThread#ApplicationThread.handleLaunchActivity() {

performLaunchActivity() {
 
  activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
 
activity.attach() {
       mWindow = new PhoneWindow(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();
  }

mInstrumentation.callActivityOnCreate(activity, r.state);

activity.performStart();
}

 handleResumeActivity() {
 if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
            }
}
}

在Activity.onCreate()中
void setContentView(int layoutResID) {
  getWindow().setContentView(layoutResID);
initActionBar();
}
PhoneWindow的setContentView方法大致遵循如下几个步骤:
   @Override
    public void setContentView(int layoutResID) {
        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); // 将Activity的布局view填充到mContentParent
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
   }

 protected DecorView generateDecor() {
        return new DecorView(getContext(), -1);
 }

在onResume()方法中执行的mWm.addView()最终执行
WindowManagerGlobal#addView(View view, ViewGroup.LayoutParams params, Display display, 
     Window parentWindow) {

            ViewRootImpl root;
            View panelParentView = null;

            int index = findViewLocked(view, false);
            
            // If this is a panel window, then find the window it is being
            // attached to for future reference.
            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                final int count = mViews.size();
                for (int i = 0; i < count; i++) {
                    if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
                        panelParentView = mViews.get(i);
                    }
                }
            }

            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);
        } catch (RuntimeException e) {
            // BadTokenException or InvalidDisplayException, clean up.
            synchronized (mLock) {
                final int index = findViewLocked(view, false);
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
            }
            throw e;
        }
    }

总结一下:

Activity在onCreate之前调用attach方法,在attach方法中会创建window对象。window对象创建时并木有创建Decor对象对象。用户在Activity中调用setContentView,然后调用window的setContentView,这时会检查DecorView是否存在,如果不存在则创建DecorView对象,然后把用户自己的View 添加到DecorView中。


详细介绍链接:http://blog.youkuaiyun.com/zizidemenghanxiao/article/details/50631148



 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值