欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

Toast弹不出来之谜

发布时间:2025/3/21 编程问答 65 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Toast弹不出来之谜 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

前言

今天早上测试应用的时候,忽然发现Toast弹不出来了,我用的华为测试机,以为是通知权限被关了,后来发现是开着的,这就纳了闷了,这个Toast工具类用了好长时间了,后来发现这Toast原来还能这样...

正文

以前工具类是这个样子的(华为的通知权限放在了其他的地方)

final public class ToastUtil {private static Toast toast;//单例的toast/*** 显示Toast*/public static void showToast(int text) {showToast(App.getInstance().getResources().getString(text));}public static void showToast(String text) {if (toast == null)toast = Toast.makeText(App.getInstance(), text, Toast.LENGTH_SHORT);toast.setText(text);toast.show();} }

平时用的都是好好的,为什么不能用了呢?

然后我通过debug发现所有路径都走了,说明是调用成功了,后来想起来,是不是子线程的问题,打印了一下线程信息:

Thread.currentThread().getName();

发现果然第一次调用没有跑在主线程中,这就尴尬了,在子线程中创建,并show()竟然没有报错,而且子线程创建的在主线程调用show()也没有报错,只是不显示

到show()的源码中发现,被try了..

/*** 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}}

修改方法

在创建和show的时候可以判断是否是主线程,如果不是就放到主线程中就ok了

修改后的代码,嗯,这样就可以了(虽然有强迫症看到这代码很不爽,但是首先得能用)

final public class ToastUtil {private static Toast toast;//单例的toast/*** 显示Toast*/public static void showToast(int text) {showToast(App.getInstance().getResources().getString(text));}public static void showToast(final String text) {if (toast == null) {//AppManager.getAppManager().currentActivity()是使用工具类获取当前Activity对象的方法AppManager.getAppManager().currentActivity().runOnUiThread(new Runnable() {@Overridepublic void run() {toast = Toast.makeText(App.getInstance(), text, Toast.LENGTH_SHORT);toast.show();}});} else {//如果show()是在子线程触发的,则在主线程来显示if ("main".equals(Thread.currentThread().getName())) {toast.setText(text);//将文本设置给toasttoast.show();} else {AppManager.getAppManager().currentActivity().runOnUiThread(new Runnable() {@Overridepublic void run() {toast.setText(text);//将文本设置给toasttoast.show();}});}}} }

ps:近些天看到了一个类似的情况,比我分析的源码更多:怀疑人生,主线程修改UI也会崩溃?

扩展

如果你因为某些情况,真的要在某个(注意是某个)子线程中弹出toast,可以使用以下方法在子线程开一个loop,这样就可以弹toast了(当然你要自己知道后果,具体百度):

thread {Looper.prepare()Toast.makeText(context, "123", Toast.LENGTH_LONG).show()Looper.loop()}

如果遇到了连续弹toast后,导致后续一段时间弹不出toast,可以使用以下方法 ,效果看起来一样,只不过每次调用都是使用的新toast对象:

//将这两行代码toast.setText(text);//将文本设置给toasttoast.show(); 改为:toast.cancel()toast = Toast.makeText(app, text, Toast.LENGTH_LONG)toast.show()

end

《新程序员》:云原生和全面数字化实践50位技术专家共同创作,文字、视频、音频交互阅读

总结

以上是生活随笔为你收集整理的Toast弹不出来之谜的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。