子线程使用Toast报错

来源:互联网 发布:微信撞库软件 编辑:程序博客网 时间:2024/06/05 04:23

在子线程中Toast了一把,竟然报错

因为Toast在service和activity中都可以执行。所以开始就认为和ui线程没有有太大的关系,现在在子线程使用Toast竟然报错!
后来查看Toast的源码,写了个demo,报错非常的清楚,终于搞定了。

05-12 15:55:36.761 13374-13981/yzx.demo.com.demo E/AndroidRuntime: FATAL EXCEPTION: Thread-2578
Process: yzx.demo.com.demo, PID: 13374
java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()
at android.os.Handler.(Handler.java:200)
at android.os.Handler.(Handler.java:114)
at yzx.demo.com.demo.MainActivityCalThread1.(MainActivity.java:0)
at yzx.demo.com.demo.MainActivity$CalThread.run(MainActivity.java:71)

1、错误的关键位置在于Toast初始化的时候,这句

 public class Toast {final Handler mHandler = new Handler();….}

2、其实在别的地方也看到过,普通线程不能直接new一个Handler
原因:

 public Handler(){ …..        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        } …..   }

3、而Looper中

 public static final Looper myLooper() {                            //这个方法是从当前线程的ThreadLocal中拿出设置的looper                 return (Looper)sThreadLocal.get();             }

而事实上子线程只是一个普通的线程,其ThreadLoacl中没有设置过Looper,所以会抛出异常

4、解决方法:子线程要想使用toast,其实源码中需要创建handler,那么就需要先Looper。prepare() 然后使用toast 然后调用Looper.loop();就可以正常使用toast了~

public void onClick(View v) {    new Thread(){    public void run() {         Log.i("log", "run");         Looper.prepare();         Toast.makeText(ActivityTestActivity.this, "toast", 1).show();        Looper.loop();// 进入loop中的循环,查看消息队列    };    }.start();

}

Looper.prepare()方法参考

//Looper

public static final void prepare() {

    if (sThreadLocal.get() !=  null) {        throw new RuntimeException("Only one Looper may be created per thread");    }    sThreadLocal.set(new Looper());}
0 0
原创粉丝点击