Toast的实现原理
通过本文,你将懂得:
1. 为什么调用Toast的子线程需要Looper.prepare()
2. Toast的Window是在哪里创建的
Toast中的IPC通信
在Toast的实现中主要有两类IPC通信:
1. 从Toast通过IPC访问NotificationManagerService(以下简称NMS)
2. 从NMS通过IPC访问Toast
其中,Toast通过SystemServer来获取NMS的远程代理对象;NMS通过Toast传递过来的远程代理对象TN来进行IPC。
TN类 典型的AIDL生成的IBinder服务端Stub类。
private static class TN extends ITransientNotification.Stub {
/**
* schedule handleShow into the right thread
*/
@Override
public void show(IBinder windowToken) {
if (localLOGV) Log.v(TAG, "SHOW: " + this);
mHandler.obtainMessage(0, windowToken).sendToTarget();
}
/**
* schedule handleHide into the right thread
*/
@Override
public void hide() {
if (localLOGV) Log.v(TAG, "HIDE: " + this);
mHandler.post(mHide);
}
}
NotificationManagerService 是通过ToastRecord中的callback来回调TN中的方法的,实际上callback就是TN在客户端中的类。
private static final class ToastRecord
{
final int pid;
final String pkg;
final ITransientNotification callback;
int duration;
Binder token;
}
源码分析
从Toast类的show()方法开始:
public void show() {
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}