- 从Toast的调用开始,静态方法makeText 构造了Toast实例
public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
@NonNull CharSequence text, @Duration int duration) {
}
- 接着调用了show(),注意看 service.enqueueToast 方法,是把Toast作为一种通知交给NotificationManagerService 处理(因为它可能很多,必须要做个队列处理)
这里的tn回调也作为参数传了过去
public void show() {
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}
INotificationManager service = getService();
String pkg = mContext.getOpPackageName();
TN tn = mTN;
tn.mNextView = mNextView;
final int displayId = mContext.getDisplayId();
try {
service.enqueueToast(pkg, tn, mDuration, displayId);
} catch (RemoteException e) {
// Empty
}
}
@VisibleForTesting
final IBinder mService = new INotificationManager.Stub() {
// Toasts
// =======================入队列操作=====================================================
@Override
public void enqueueToast(String pkg, ITransientNotification callback, int duration,
int displayId)
{
record = new ToastRecord(callingPid, pkg, callback, duration, token,
displayId);
mToastQueue.add(record);
}
- 取出消息showNextToastLocked ,回调Toast的内部类show()方法
record.callback.show
void showNextToastLocked() {
ToastRecord record = mToastQueue.get(0);
while (record != null) {
if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback);
try {
record.callback.show(record.token);
scheduleDurationReachedLocked(record);
}
}
}
//Toast->TN
public void show(IBinder windowToken) {
if (localLOGV) Log.v(TAG, "SHOW: " + this);
mHandler.obtainMessage(SHOW, windowToken).sendToTarget();
}
-
最后调用到Toast的 public void handleShow(IBinder windowToken) 方法
其内部实现跟dialog类似,都是创建view 通过WM.addView 显示出来。 -
问:Toast可以在子线程弹出吗
答:肯定可以
看他另外一个构造方法,就是需要你自己构建looper
public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
@NonNull CharSequence text, @Duration int duration)
if (looper == null) {
// Use Looper.myLooper() if looper is not specified.
looper = Looper.myLooper();
if (looper == null) {
throw new RuntimeException(
"Can't toast on a thread that has not called Looper.prepare()");
}
}
//使用方法
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(MainActivity.this, "show", Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start();
网友评论