Activity、View、Window和WindowManager

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

一、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



 



### 关系 Activity 并不负责视图控制,它只是控制生命周期处理事件,真正控制视图的是 Window。一个 Activity 包含了一个 WindowWindow 才是真正代表一个窗口。Activity 就像一个人机交互界面,统筹视图的添加与显示,以及通过其他回调方法,来与 Window、以及 View 进行交互。整个过程 Activity 表面上参与度比较低,Activity 持有 Window 的对象,ViewWindow 上的增删等操作又是通过 WindowManager 来管理的,而 WindowManager 又是通过 Binder 机制获取到的 WMS 的映射,WMS 把 View 真正显示到屏幕上 [^2][^3]。 ### 使用方法 #### Activity 的使用方法 创建一个 Activity 需要继承 `Activity` 或其子类,并重写相关的生命周期方法,例如 `onCreate()` 方法用于初始化界面。在 `AndroidManifest.xml` 中注册该 Activity,然后可以通过 `Intent` 来启动 Activity。以下是一个简单的示例: ```java import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } ``` 在 `AndroidManifest.xml` 中注册: ```xml <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ``` #### Window 的使用方法 通常不需要直接操作 Window,而是通过 Activity 间接操作。例如,在 Activity 中可以通过 `getWindow()` 方法获取当前 Activity 对应的 Window 对象,然后可以设置 Window 的属性,如背景颜色、标题等。示例如下: ```java import android.app.Activity; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } } ``` ### 区别 Activity 主要负责管理应用程序的生命周期处理用户交互事件,是用户与应用程序交互的入口。而 Window 主要负责管理视图的显示,是视图的容器,为 View 提供显示的窗口。Activity 侧重于业务逻辑事件处理,Window 侧重于视图的管理显示 [^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值