改变 Toast 的位置
Toast toast = Toast.makeText(this, "Gravity", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.BOTTOM|Gravity.RIGHT, 0, 0);
toast.show();
自定义 Toast 的布局
LayoutInflater inflater = getLayoutInflater();
# 解析自定义布局,父布局传入肯
View layout = inflater.inflate(R.layout.toast_layout, (ViewGroup) findViewById(R.id.toast_layout_root));
# 填充信息,比如设置文字,图片等
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("This is a custom Toast.");
# 显示 Toast
Toast toast = new Toast(getApplicationContext());
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
避免内存泄露
下列这段简单的代码,居然可能会出现内存泄露!
Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();
原因在于:如果在 Toast 消失之前,Toast 持有了当前 Activity,而此时,用户点击了返回键,导致 Activity 无法被 GC 销毁, 这个 Activity 就引起了内存泄露.
一个很简单的解决方法:所有只要和布局无关的 Context 都可以传入 ApplicationContext
, 此避免内存泄露的方法同样试用于其他需要传入 Context 的地方。就像这样:
Toast toast = Toast.makeText(getApplicationContext(), "Gravity", Toast.LENGTH_SHORT);
显示时间只有 LENGTH_SHORT, LENGTH_LONG 可以选择
frameworks/base/services/java/com/android/server/NotificationManagerService.java
查看源码可以发现,没有其他显示时间长度可以选择。
private static final int LONG_DELAY = 3500; // 3.5 seconds
private static final int SHORT_DELAY = 2000; // 2 seconds
private void scheduleTimeoutLocked(ToastRecord r) {
mHandler.removeCallbacksAndMessages(r);
Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r);
long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
mHandler.sendMessageDelayed(m, delay);
}
show() 方法其实是入队操作
/**
* Show the view for the specified duration.
*/
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;
try {
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}
普通应用的 Toast 显示数量是有限制的
查看
frameworks/base/services/java/com/android/server/NotificationManagerService.java
中的入队方法
enqueueToast
发现非系统应用是有最大总数限制的,而系统应用没有
// 非系统Toast,每个pkg在当前mToastQueue中Toast有总数限制,不能超过MAX_PACKAGE_NOTIFICATIONS
if (!isSystemToast) {
int count = 0;
final int N = mToastQueue.size();
for (int i=0; i= MAX_PACKAGE_NOTIFICATIONS) {
Slog.e(TAG, "Package has already posted " + count + " toasts. Not showing more. Package=" + pkg);
return;
}
}
}
}