最近在些一个ToastUtil,用于统一新公司项目中的toast提示,先贴出ToastUtil的代码吧,只有简短几行
package com.luluyou.licai.util;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.StringRes;
import android.view.Gravity;
import android.widget.Toast;
import com.luluyou.licai.system.ZKBCApplication;
import java.lang.ref.WeakReference;
public class ToastUtil {
private static WeakReference<Toast> toastWeakReference;
public static void shortToast(CharSequence character){
toastOnUIThread(character,Toast.LENGTH_SHORT,false);
}
public static void shortToast(@StringRes int resId){
shortToast(ZKBCApplication.getInstance().getText(resId));
}
public static void shortCenterToast(CharSequence character){
toastOnUIThread(character,Toast.LENGTH_SHORT,true);
}
public static void shortCenterToast(@StringRes int resId){
shortCenterToast(ZKBCApplication.getInstance().getText(resId));
}
private static void toastOnUIThread(CharSequence character,/*@Toast.Duration*/ int duration,boolean isCenter){
if(Looper.myLooper() == Looper.getMainLooper()){ //主线程
toast(character,duration,isCenter);
}else{ //子线程
new Handler(Looper.getMainLooper()).post(() -> toast(character,duration,isCenter));
}
}
private static void toast(CharSequence character,/*@Toast.Duration*/ int duration,boolean isCenter){
if(toastWeakReference == null || toastWeakReference.get() == null) {
toastWeakReference = new WeakReference(Toast.makeText(ZKBCApplication.getInstance(),character,duration));
}
if(isCenter){
toastWeakReference.get().setGravity(Gravity.CENTER, 0, 0);
}else{
// toastWeakReference.get().setGravity(Gravity.CENTER|Gravity.BOTTOM, 0, ZKBCApplication.getInstance().getResources().getDimensionPixelSize(
// com.android.internal.R.dimen.toast_y_offset)); //不能使用隐藏得内部资源,<dimen name="toast_y_offset">64dip</dimen>
toastWeakReference.get().setGravity(Gravity.CENTER|Gravity.BOTTOM, 0, Helper.dpToPx(64,ZKBCApplication.getInstance()));
}
toastWeakReference.get().setText(character);
toastWeakReference.get().show();
}
}
引出一个需求,在非ui线程也可以使用toast
所以有了这行代码:
else{ //子线程
new Handler(Looper.getMainLooper()).post(() -> toast(character,duration,isCenter));
}
上面的代码,是将toast(…)的执行放到了主线程中了.
否则,在主线程中调用Toast,会出现如下异常
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
出现这个错误的原因是toast依赖于handle,用于处理视图的展示隐藏时间,而主线程(UI线程)是实现了Looper的,子线程若没有looper,Toast进行执行前的检查会抛出异常。
看源码可知,Toast 实际是window.addView(),在window上添加一个视图,通过handle控制展示隐藏。
这部分源码的分析,下次再写。