本文主要是介绍一场Toast引发的血案---WindowManager,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在一场Toast引发的血案—Toast的显示中,已经大致了解了Toast的显示过程,但是还是有很多疑惑,Toast最终现实的时候是要通过WindowManager添加到一个Window的,但是这个WindowManager是哪个WindowManager,带着这个疑惑,我们开始深入。
可能在此之前对Window不是很了解,但这不影响对WindowManager的理解,只需要大概知道一个Activity,一个Dialog在显示的时候对应这一个Window即可。
WindowManger对象的产生
要使用WindowManger必须要获取WindowManger,获取WindowManger是通过context.getSystemService(Context.WINDOW_SERVICE)
,但是WindowManager对象究竟是怎么产生的呢?在ContextImpl
中看到了下面的代码:
@Override
public Object getSystemService(String name) {return SystemServiceRegistry.getSystemService(this, name);
}
再跟踪到SystemServiceRegistry
中发现了下面的代码:
registerService(Context.WINDOW_SERVICE, WindowManager.class,new CachedServiceFetcher<WindowManager>() {@Overridepublic WindowManager createService(ContextImpl ctx) {return new WindowManagerImpl(ctx);}});
感觉这和我的理解不太一样,WindowManager不应该是一个单例吗?再到WindowManagerImpl
中看下。突然发现了下面的代码:
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
在我们经常使用的addView
函数中也有mGlobal
:
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {......mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
removeView
函数就直接使用了mGlobal.removeView
public void removeView(View view) {mGlobal.removeView(view, false);
}@Override
public void removeViewImmediate(View view) {mGlobal.removeView(view, true);
}
到这里,我们已经知道每个WindowManager的实例都不一样,但是每部都是在使用WindowManagerGlobal
的单利对象对Window上的控件进行管理。为了不影响对Toast的分析,WindowManagerGlobal
我会在后面单独分析。
WindowManager的获取
上面分析了WindowManger对象的产生,接下来就要分析下WindowManager对象的获取。在没有看相关源码之前,我一直以为context.getSystemService(Context.WINDOW_SERVICE)
在那都是一样的,可以不用特别关注context
的区别,直到我在Activity
中看到了下面的代码:
public Object getSystemService(@ServiceName @NonNull String name) {......if (WINDOW_SERVICE.equals(name)) {return mWindowManager;} else if (SEARCH_SERVICE.equals(name)) {ensureSearchManager();return mSearchManager;}return super.getSystemService(name);
}
wc,Activity
还针对getSystemService
进行了特殊处理,如果是为了获取WindowManager或者SearchManager,就会去拿Activity
的属性mWindowManager
。看下mWindowManager
是如何产生的
代码段1
mWindow = new PhoneWindow(this, window, activityConfigCallback);
代码段2
mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),mToken, mComponent.flattenToString(),(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
代码段3
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,boolean hardwareAccelerated) {mAppToken = appToken;mAppName = appName;mHardwareAccelerated = hardwareAccelerated|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);if (wm == null) {wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);}mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
发现最终mWindowManager
是由WindowManagerImpl
的createLocalWindowManager
方法产生的,而createLocalWindowManager
最终会调用
return new WindowManagerImpl(mContext, parentWindow);
突然感觉有回到了上一部分。
有了Activity
的教训,我赶紧去看了Service
和Applicaiton
,最终确认没有都是直接调用了ContextImpl
的getSystemService
方法,并没有对服务进行特殊的处理。
总结
上面分析了WindowManager
的产生和获取,可以发先每个context都可以获取自己的WindowManager
实例,以便对Window
进行操作,但是WindowManager
实例实际上是通过WindowManagerGlobal
的单利对象对Window进行操作的。
这篇关于一场Toast引发的血案---WindowManager的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!