首先,所有 Android
进程的视图显示都需要依赖于一个窗口。而这个窗口对象,被记录在了我们的 WindowManagerService(后面简称 WMS) 核心服务中。WMS 是专门用来管理应用窗口的核心服务。当 Android
进程需要构建一个窗口的时候,必须指定这个窗口的类型。 Toast
的显示也同样要依赖于一个窗口, 而它被指定的类型是:
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;//系统窗口
可以看出, Toast
是一个系统窗口,这就保证了 Toast
可以在 Activity
所在的窗口之上显示,并可以在其他的应用上层显示。那么,这就有一个疑问:
“如果是系统窗口,那么,普通的应用进程为什么会有权限去生成这么一个窗口呢?”
我们先来看下 Toast
从显示到隐藏的整个流程:
// code Toast.java
public void show() {
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}
INotificationManager service = getService();//调用系统的notification服务
String pkg = mContext.getOpPackageName();
TN tn = mTN;//本地binder
tn.mNextView = mNextView;
try {
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}
我们通过代码可以看出,当 Toast
在 show
的时候,将这个请求放在 NotificationManager
所管理的队列中,并且为了保证 NotificationManager
能跟进程交互, 会传递一个 TN
类型的 Binder
对象给 NotificationManager
系统服务。而在 NotificationManager
系统服务中:
//code NotificationManagerService
public voi