package com.hjq.toast; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.widget.Toast; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; /** * author : Android 轮子哥 * github : https://github.com/getActivity/ToastUtils * time : 2018/11/12 * desc : Toast 默认处理器 */ public class ToastStrategy extends Handler implements IToastStrategy { /** 延迟时间 */ private static final int DELAY_TIMEOUT = 200; /** 显示吐司 */ private static final int TYPE_SHOW = 1; /** 继续显示 */ private static final int TYPE_CONTINUE = 2; /** 取消显示 */ private static final int TYPE_CANCEL = 3; /** 队列最大容量 */ private static final int MAX_TOAST_CAPACITY = 3; /** 吐司队列 */ private volatile Queue<CharSequence> mQueue; /** 当前是否正在执行显示操作 */ private volatile boolean mShow; /** 吐司对象 */ private Toast mToast; public ToastStrategy() { super(Looper.getMainLooper()); mQueue = getToastQueue(); } @Override public void bind(Toast toast) { mToast = toast; } @Override public void show(CharSequence text) { if (mQueue.isEmpty() || !mQueue.contains(text)) { // 添加一个元素并返回true,如果队列已满,则返回false if (!mQueue.offer(text)) { // 移除队列头部元素并添加一个新的元素 mQueue.poll(); mQueue.offer(text); } } if (!mShow) { mShow = true; // 延迟一段时间之后再执行,因为在没有通知栏权限的情况下,Toast 只能显示当前 Activity // 如果当前 Activity 在 ToastUtils.show 之后进行 finish 了,那么这个时候 Toast 可能会显示不出来 // 因为 Toast 会显示在销毁 Activity 界面上,而不会显示在新跳转的 Activity 上面 sendEmptyMessageDelayed(TYPE_SHOW, DELAY_TIMEOUT); } } @Override public void cancel() { if (mShow) { mShow = false; sendEmptyMessage(TYPE_CANCEL); } } @Override public void handleMessage(Message msg) { switch (msg.what) { case TYPE_SHOW: // 返回队列头部的元素,如果队列为空,则返回null CharSequence text = mQueue.peek(); if (text != null) { mToast.setText(text); mToast.show(); // 等这个 Toast 显示完后再继续显示,要加上一些延迟 // 不然在某些手机上 Toast 可能会来不及消失就要进行显示,这样是显示不出来的 sendEmptyMessageDelayed(TYPE_CONTINUE, getToastDuration(text) + DELAY_TIMEOUT); } else { mShow = false; } break; case TYPE_CONTINUE: // 移除并返问队列头部的元素,如果队列为空,则返回null mQueue.poll(); if (!mQueue.isEmpty()) { sendEmptyMessage(TYPE_SHOW); } else { mShow = false; } break; case TYPE_CANCEL: mShow = false; mQueue.clear(); mToast.cancel(); break; default: break; } } /** * 获取吐司队列 */ public Queue<CharSequence> getToastQueue() { return new ArrayBlockingQueue<>(MAX_TOAST_CAPACITY); } /** * 根据文本来获取吐司的显示时长 */ public int getToastDuration (CharSequence text) { // 如果显示的文字超过了10个就显示长吐司,否则显示短吐司 return text.length() > 20 ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT; } }