子线程使用Toast报错

在子线程中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.MainActivity CalThread 1.(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());

}
在 Qt 中,线程写文件需要注意一些问题。 首先,线程不能直接访问 GUI 线程中的 UI 控件,因为 UI 控件只能在主线程中被访问。因此,在线程中进行文件操作时,应该使用信号与槽机制将文件操作的结果传递给主线程,在主线程中进行 UI 更新。 其次,如果在线程中打开了文件,需要在线程中进行文件的写入操作。如果在主线程中打开了文件,那么在线程中进行文件的写入操作时,可能会出现 “device not open” 的错误。 下面是一个在线程中写文件的示例代码: ```cpp // MyWorkerThread.h #include <QThread> #include <QFile> class MyWorkerThread : public QThread { Q_OBJECT public: MyWorkerThread(QObject *parent = nullptr); ~MyWorkerThread(); void run() override; signals: void finished(); void error(QString err); private: QFile m_file; }; // MyWorkerThread.cpp #include "MyWorkerThread.h" MyWorkerThread::MyWorkerThread(QObject *parent) : QThread(parent) { m_file.setFileName("test.txt"); } MyWorkerThread::~MyWorkerThread() { if (m_file.isOpen()) { m_file.close(); } } void MyWorkerThread::run() { if (!m_file.open(QIODevice::WriteOnly)) { emit error("Failed to open file."); return; } QTextStream out(&m_file); out << "Hello, World!" << endl; m_file.flush(); m_file.close(); emit finished(); } ``` 在上面的示例代码中,我们在线程中创建了一个 QFile 对象,然后在 run() 函数中打开了这个文件,写入了一些数据,并在结束时关闭了文件。我们还定义了两个信号:finished() 和 error(),分别用于通知主线程操作完成和发生错误。 当然,你需要在主线程中创建一个 MyWorkerThread 对象,并将它的 finished() 和 error() 信号连接到相应的槽函数上。另外,在启动线程之前,你需要调用 moveToThread() 函数将 MyWorkerThread 对象移到线程中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值