Android进阶:六、在子线程中直接使用 Toast 及其原理
一般我们都把Toast当做一个UI控件在主线程显示。但是有时候非想在子线程中显示Toast,就会使用Handler切换到主线程显示。
但是子线程中真的不能直接显示Toast吗?
答案是:当然可以。
那应该怎么操作呢?在当前线程中先初始化一个Looper即可!
Looper.prepare();
Toast.makeText(getBaseContext(), "text", Toast.LENGTH_LONG).show();
Looper.loop();
为什么在子线程中使用Toast需要初始一个Looper呢? 我们看看源代码:
public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
return makeText(context, null, text, duration);
}
public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
@NonNull CharSequence text, @Duration int duration) {
Toast result = new Toast(context, looper);
...
return result;
}
以上是我们使用Toast时调用的静态方法,可以看到第二个方法有个参数Looper,虽然我们平时用的时候都传入的是null,那这个Looper究竟有什么用呢?我们看看Toast的构造函数:
public Toast(@NonNull Context context, @Nullable Looper looper) {
mContext = context;
mTN = new TN(context.getPackageName(), looper);
}
可以看出这个Looper其实是TN在用,我们看看它的构造函数:
TN(String packageName, @Nullable Looper looper) {
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()");
}
}
}
以上代码有简化。可以看出当Looper为null的时候,会通过Looper.myLooper获取一个当前的Looper。我们知道在主线程中系统已经为我们初始化了一个mainLooper,所以我们一般不用管。但是当我们子线程中如果没有初始化Looper,这里调用Looper.myLooper就获取不到一个Looper,则会抛出异常。所以当我们在子线程中使用Toast,使用Looper.prepare()方法初始化一个Looper并用Looper.loop()让它启动起来即可。
所以我们可以封装一个可以在任何线程使用的Toast。
private static Toast toast = null;
public static void showToast(Context context, String text) {
Looper myLooper = Looper.myLooper();
if (myLooper == null) {
Looper.prepare();
myLooper = Looper.myLooper();
}
if (toast == null) {
toast = Toast.makeText(context, text, Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
}
toast.show();
if ( myLooper != null) {
Looper.loop();
myLooper.quit();
}
}
我们初始化Toast之前先判断当前线程的looper是否为空,为空则初始化一个新的myLooper,然后在调用Toast的show方法之后让looper启动起来即可。因为Looper的loop()方法是无限循环的,为了防止Looper阻塞线程,导致内存泄漏应该及时退出Looper。
Android进阶:六、在子线程中直接使用 Toast 及其原理的更多相关文章
- Android利用Looper在子线程中改变UI
MainActivity如下: package cn.testlooper; import android.app.Activity; import android.os.Bundle; import ...
- Android开发之在子线程中使用Toast
在子线程中使用Toast的时候,出现Force close. 错误提示:Can't create handler inside thread that has not called Looper.pr ...
- Android在子线程中更新UI(二)
MainActivity如下: package cc.testui2; import android.os.Bundle; import android.view.View; import andro ...
- Android在子线程中更新UI(一)
MainActivity如下: package cc.testui1; import android.os.Bundle; import android.os.Handler; import andr ...
- Android开发UI之在子线程中更新UI
转自第一行代码-Android Android是不允许在子线程中进行UI操作的.在子线程中去执行耗时操作,然后根据任务的执行结果来更新相应的UI控件,需要用到Android提供的异步消息处理机制. 代 ...
- 【第三篇】学习 android 事件总线androidEventbus之发布事件,子线程中接收
发送和接收消息的方式类似其他的发送和接收消息的事件总线一样,不同的点或者应该注意的地方: 1,比如在子线程构造方法里面进行实现总线的注册操作: 2,要想子线程中接收消息的功能执行,必须启动线程. 3, ...
- 老问题:Android子线程中更新UI的3种方法
在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 方法一:用Handler 1.主线程中定义Handler: Handle ...
- android 不能在子线程中更新ui的讨论和分析
问题描写叙述 做过android开发基本都遇见过 ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是仅仅能在主线程中更改 ui.子线程要 ...
- android UI 操作 不要在子线程中操作UI
不管是android ,还是 ios ,请不要在子线程中操作UI,有时有些崩溃,从报错上看不出什么原因,就有可能是子线程操作了UI:切记,切记! 请放在主线程例: activity.runOnUiTh ...
随机推荐
- 基础概念【softmax|normalizatoin|standardization】
目录 一.softmax 二.normalization 三.standardization 一.softmax 为什么使用softmax,不用normalization? “max” because ...
- MapReduce-TextInputFormat 切片机制
MapReduce 默认使用 TextInputFormat 进行切片,其机制如下 (1)简单地按照文件的内容长度进行切片 (2)切片大小,默认等于Block大小,可单独设置 (3)切片时不考虑数据集 ...
- JetBrain server certificate is not trusted 弹出框
To get rid of the pop up message go to below location and click on Accept non-trusted certificates a ...
- react native 安卓home返回键页面刷新
import { withNavigationFocus } from 'react-navigation'; class Warngreete extends React.Component { c ...
- http升级https的时候,遇到一个问题
问题: Mixed Content: The page at 'https://api.xxxx.com/test' was loaded over HTTPS, but requested an i ...
- awk和sed截取nginx和tomcat时间段日志
1 nginx日志截取示例 日志路径:/usr/local/nginx/logs, 截取access.log中2019年3月24日17点00~02之间的日志: 写法1: cat access.log ...
- Springboot项目打包后的页面丢失问题(thymeleaf报错)
遇到的问题目前找到两种: 返回视图路径以/开头,例如 /test/hello 在thymeleaf页面中,引入的页面以/开头,例如:<footer th:replace="/index ...
- python制作串口工具
# coding:utf-8import timeimport serialimport stringimport binasciiimport linecache FilePath="G: ...
- (转)Java语法----Java中equals和==的区别
转载地址:https://www.cnblogs.com/smyhvae/p/3929585.html 一.java当中的数据类型和“==”的含义: 基本数据类型(也称原始数据类型) :byte,sh ...
- 逆向 make 打包错误解决方案 make: *** [internal-package] Error 2
修改deb.mk文件第6行的压缩方式为gzip vim $THEOS/makefiles/package/deb.mk _THEOS_PLATFORM_DPKG_DEB_COMPRESSION ?= ...