Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();

在子线程里创建 Toast 时出现报错:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare().
在没有调用 Looper.prepare() 的线程里,无法创建 handler

原因是修改 UI 需要在主线程里。

1. Thread

因为线程需要 Looper 来循环处理消息,但是子线程中默认是没有 Looper 的,查看一下 Looper 的源码,类注释如下:

/**  * Class used to run a message loop for a thread.  Threads by default do  * not have a message loop associated with them; to create one, call  * {@link #prepare} in the thread that is to run the loop, and then  * {@link #loop} to have it process messages until the loop is stopped.  *  * 

Most interaction with a message loop is through the * {@link Handler} class. * *

This is a typical example of the implementation of a Looper thread, * using the separation of {@link #prepare} and {@link #loop} to create an * initial Handler to communicate with the Looper. * *

  *  class LooperThread extends Thread {  *      public Handler mHandler;  *  *      public void run() {  *          Looper.prepare();  *  *          mHandler = new Handler() {  *              public void handleMessage(Message msg) {  *                  // process incoming messages here  *              }  *          };  *  *          Looper.loop();  *      }  *  }
*/

注释里说明了线程默认是没有 Looper 的,需要在线程里手动调用 Looper.prepare() 来创建 Looper,并且调用 Looper.loop() 来遍历消息。并且还附带了一个例子。

所以我们直接按照官方给的例子调用即可:

new Thread(new Runnable() {    @Override    public void run() {        Looper.prepare();        Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();        Looper.loop();    }}).start();

2. Handler

如果直接在子线程里创建 new Handler(),也会报同样的错误,因为子线程默认是没有 Looper 的。
可以使用 public Handler(Looper looper) 构造方法创建 Handler,传递主线程的 Looper

new Handler(Looper.getMainLooper()).post(new Runnable() {    @Override    public void run() {        Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();    }});

3. runOnUiThread

如果是在 Activity 里,可以使用 runOnUiThread

runOnUiThread(new Runnable() {    @Override    public void run() {        Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();    }});

或者

if (mContext instanceof Activity) {    ((Activity) mContext).runOnUiThread(new Runnable() {        @Override        public void run() {            Toast.makeText(mContext, "msg", Toast.LENGTH_SHORT).show();        }    });

参考

  1. Can’t create handler inside thread that has not called Looper.prepare()
  2. Android 子线程创建handler
  3. Android 带你彻底理解跨线程通信之Handler机制

更多相关文章

  1. 基于TCP和多线程实现无线鼠标键盘-Socket(2)
  2. ue4 创建Android和ios ar应用
  3. android 中文 api (71) —— BluetoothServerSocket[蓝牙]
  4. Android中有关Handler的使用(三)
  5. TTS源码解析
  6. android平台上的文件下载,文件和文件的操作
  7. Android(安卓)Studio中与网站通信
  8. Android的onCreateOptionsMenu()创建菜单Menu详解
  9. Android异步加载图片,并缓存到SD卡

随机推荐

  1. 浅析Android(安卓)View(一)
  2. Glide详细了解优缺点
  3. DynamicAPK基本概念
  4. Android手机开发总结
  5. Java内部类精炼详解—由Android点击事件
  6. 关于android UI布局自适应
  7. Android(安卓)UI优化之OverDraw
  8. 快速提高Android开发效率的Web工具
  9. 第三部分:Android(安卓)应用程序接口指南-
  10. Android(安卓)Mvp模式详解(Kotlin篇)