WindowManager实例化流程和View添加流程

  1. WindowManager获取

<1>通过Context获取WindowManager系统服务:

WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

<2>在Activity类型的Context中:getSystemService的实现

//Activity.java
 public Object getSystemService(@ServiceName @NonNull String name) {
        ……
        if (WINDOW_SERVICE.equals(name)) {
            return mWindowManager;// <----------------看这里
        } 
        ……
        return super.getSystemService(name);
    }

<3>在Activity中mWindowManager的赋值

//Activity.java
    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,
            Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);
        ……
        mWindow = new PhoneWindow(this, window, activityConfigCallback);// <-----看这里
        mWindow.setCallback(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();// <----------------看这里
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);
    }

getWindowManager方法的实现

//Window.java 
//PhoneWindow继承Window,并没有重写getWindowManager()
 public WindowManager getWindowManager() {
        return mWindowManager;
    }

setWindowManager方法的赋值

 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);
    }

setWindowManager的wm参数

(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)
//context是attach的第一个参数attach(Context context,

attach中第一个参数context的来源,从ActivityThread的performLaunchActivity方法
可以看出appContext的是一个ContextImpl对象

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ……
        ContextImpl appContext = createBaseContextForActivity(r);// <------看这里
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
           ……
        } catch (Exception e) {
           ……
        }
        try {
           ……
            if (activity != null) {
               ……
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
                // ^------看这里
               ……

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
           ……
        }
        return activity;
    }

ContextImp的getSystemService的实现

@Override
public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

进入SystemServiceRegistry中,可以看出WindowManager是通过static{}块预先加载的,最后通过CachedServiceFetcher的createService创建,也就是new WindowManagerImpl(ctx);ctx参数时ContextImp对象本身,也就是Activity中attach的第一个参数attach(Context context,

private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
static {
        ……
        registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
            @Override
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx);
            }});
            ……
        }
 private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }            
 public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

回到Activity的attach方法,可以理解为

final void attach(Context context, ……) {
        attachBaseContext(context);
        ……
        mWindow = new PhoneWindow(this, window, activityConfigCallback);// <-----看这里
        mWindow.setCallback(this);
        ……
        mWindow.setWindowManager(new WindowManagerImpl(context,mWindow),……);
                // ^----------------看这里
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();// <----------------看这里
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);
    }

再来看Window 的setWindowManager方法,可以知道 mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);

//window.java
 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.java
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mContext, parentWindow);
    }

结论:Activity类型的Context中获取的WindowManager就是new WindowManagerImpl(mContext, parentWindow)
,mContext为ContextImpl类型,来源是从ActivityThread的performLaunchActivity中传递到Activity的attach中的。parentWindow是attach中创建的PhoneWindow 这样可以知道了WindowManager实际是一个WindowManagerImpl对象

  1. WindowManager添加视图

WindowManager的addView的实现是调用WindowManagerImpl的addView

//WindowManagerImpl.java

private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

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

mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);参数解释:view, param是addView传进来的, mContext.getDisplay()是默认显示,主屏,mParentWindow也就是Activity中attach中创建的PhoneWindow

WindowManagerGlobal的addView

//WindowManagerGlobal.java

private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams =
            new ArrayList<WindowManager.LayoutParams>();
private final ArraySet<View> mDyingViews = new ArraySet<View>();
    
public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        ……

        ViewRootImpl root;
        ……
        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) {
               ……
            }
        }
    }

可以知道这里面,ViewRootImpl <—> View <—> ViewGroup.LayoutParams是一一对应的,存储在对应数组里面。mDyingViews存放的是调用removeViewImmediate要移除,但是还未移除的View

开始看root.setView(view, wparams, panelParentView)方法

//ViewRootImpl.java

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
……
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();
……
//调用WindowManagerService 创建 Surface
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
……
     }
    
@Override
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        checkThread();
        mLayoutRequested = true;
        scheduleTraversals();
        }
    }

后面就是View的绘制流程doTraversal(),performTraversals(),performMeasure(),
mView.measure(),performLayout(),mView.layout(),performDraw(),draw().这样界面就在屏幕上显示出来了


此文要是对你有帮助,如果方便麻烦点个赞,谢谢!!!

猜你喜欢

转载自blog.csdn.net/kingyc123456789/article/details/107335217