为什么我可以通过Looper在非UI线程触摸UI界面?

3
    thread = new Thread() {
        public void run() {
            super.run();
            System.out.println("run:" + Thread.currentThread().getName());
            Looper.prepare();
            handler = new Handler();
            Looper.loop();
        };
    };
    thread.start();

然后

    handler.post(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(MActivity.this,Thread.currentThread().getName(),0).show();
        }
    });

代码运行正确。

但是 Toast 显示出来的是 "Thread-217"。

这意味着该 Toast 是从非 UI 线程中显示。

为什么会这样?


非常抱歉,我知道答案了。Toast 是一个特殊的 UI 元素,可以从任何线程中显示。但是其他 UI 元素,例如 Button 和 TextView ,只能在 UI 线程中操作。

所以,我的代码运行正确,但是当你将 Toast 更改为 Button 时,它会崩溃。


因为您在后台线程中创建了处理程序。 - pskink
@pskink它说UI操作必须放在UI线程上? - Tony
2个回答

1
您正在使用可运行的方式在UI线程中显示toast,这就是为什么出错的原因。
  Thread background = new Thread(new Runnable() {   
        public void run() {
                         // Send message to handler
                            handler.sendMessage(msgObj);
                        }
      };




      private final Handler handler = new Handler() {
               public void handleMessage(Message msg) {
                  //Catch the response and show the toast
                  String aResponse = msg.getData().getString("message");

                  Toast.makeText(getBaseContext(),"Not Got Response From Server.",
                         Toast.LENGTH_SHORT).show();
                                }
          };

我意思是toast.show()应该在单独的线程上运行,因为handler是在非UI线程中创建的。但是代码运行正确。所以我们可以在非UI线程上操作UI吗? - Tony
你不应该在非 UI 线程上显示 Toast,否则程序一定会崩溃...Toast 应该始终在 UI 线程中。 - Sreedev

1

您必须在 UiThread 中创建 Handler。Handler 将消息发送到创建它的线程。

handler = new Handler();

thread = new Thread() {
        public void run() {
            super.run();
            System.out.println("run:" + Thread.currentThread().getName());
            Looper.prepare();
            Looper.loop();
        };
    };
    thread.start();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接