首页 > 程序开发 > 移动开发 > 其他 >

PoliceManager与DecorWindow

2017-01-19

(1)PolicyManager是一个策略工厂;(2)Policy是各种一个的生产者,具体是由PolicyManager进行生产操作;(3)PhoneWindow是Android中的最基本的窗口系统,每个Activity 均会创建一个PhoneWindow对象,是Activity和整个View系统交互的接口。

先看UML类图:

\

(1)PolicyManager是一个策略工厂;

(2)Policy是各种一个的生产者,具体是由PolicyManager进行生产操作;

(3)PhoneWindow是Android中的最基本的窗口系统,每个Activity 均会创建一个PhoneWindow对象,是Activity和整个View系统交互的接口。

(4)DecorView是当前Activity所有View的祖先,它并不会向用户呈现任何东西,它主要有如下几个功能:

A. Dispatch ViewRoot分发来的key、touch、trackball等外部事件;

B. DecorView有一个直接的子View,我们称之为System Layout,这个View是从系统的Layout.xml中解析出的,它包含当前UI的风格,如是否带title、是否带process bar等。可以称这些属性为Window decorations。

C. 作为PhoneWindow与ViewRoot之间的桥梁,ViewRoot通过DecorView设置窗口属性。

1、Activity的构成

当我们写Activity时会调用setContentView()方法,来加载布局,setContentView()方法源码如下:

public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
}
 public Window getWindow() {
        return mWindow;
}
那么这个mWindow是在什么地方创建的呢?

1.1 Window的创建

Activity#attach

 final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
        attachBaseContext(context);
        mFragments.attachHost(null /*parent*/);
        mWindow = new PhoneWindow(this);
        ...
}
原来mWindow指的就是PhoneWindow,PhoneWindow是继承抽象类Window的,这样就知道getWindow()得到的是一个PhoneWindow,我们来看看PhoneWindow.java的setContentView()方法(PhoneWindow.java):
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor();  //关键
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            view.setLayoutParams(params);
            final Scene newScene = new Scene(mContentParent, view);
            transitionTo(newScene);
        } else {
            mContentParent.addView(view, params);
        }
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }
其中,在installDecor()方法中创建了DecorView。

DecorView就是Activity中的根View。接着查看DecorView的源码,发现DecorView是PhoneWindow类的内部类,并且继承FrameLayout。

1.2 总结

一个Activity包含一个window对象,这个对象是由PhoneWindow来实现的,PhoneWindow将DecorView做为整个应用窗口的根View,而这个DecorView又将屏幕划分为两个区域一个是TitleView一个是ContentView,而我们平常做应用所写的布局正是展示在ContentView中的。

\


2、Activity的显示

每一个Activity组件都有一个关联的Window对象,用来描述一个应用程序窗口。每一个应用程序窗口内部又包含有一个View对象,用来描述应用程序窗口的视图。上文分析了创建DecorView的过程,现在则要把DecorView添加到Window对象中。这个过程与Activity的创建过程相关:
首先,在ActivityThread#handleLaunchActivity中启动Activity,在这里面会调用到Activity#onCreate方法,从而完成上面所述的DecorView创建动作,当onCreate()方法执行完毕,在handleLaunchActivity方法会继续调用到ActivityThread#handleResumeActivity方法。

2.1ActivityThread#handleResumeActivity

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

    if (r != null) {
        final Activity a = r.activity;

        //...
        if (r.window == null && !a.mFinished && willBeVisible) {
            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 = true;
                wm.addView(decor, l); // 调用addView方法
            }
            //...
        }
    }
}
在该方法内部,获取该activity所关联的window对象,DecorView对象,以及windowManager对象,而WindowManager是抽象类,它的实现类是WindowManagerImpl,所以后面调用的是WindowManagerImpl#addView方法,我们看看源码:

public final class WindowManagerImpl implements WindowManager {    
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    ...
    @Override
    public void addView(View view, ViewGroup.LayoutParams params) {
        mGlobal.addView(view, params, mDisplay, mParentWindow);
    }
}
接着看WindowManagerGlobal#addView方法:

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

        ViewRootImpl root;
        View panelParentView = null;

        synchronized (mLock) {
            ...

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

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

先看①号代码处,实例化了ViewRootImpl类,接着,在②号代码处,调用ViewRootImpl#setView方法,并把DecorView作为参数传递进去,在这个方法内部,会通过跨进程的方式向WMS(WindowManagerService)发起一个调用,从而将DecorView最终添加到Window上,在这个过程中,ViewRootImpl、DecorView和WMS会彼此关联,至于详细过程这里不展开来说了。
最后通过WMS调用ViewRootImpl#performTraverals方法开始View的测量、布局、绘制流程。

相关文章
最新文章
热点推荐