java - 为什么 UI 线程被阻塞?

标签 java android multithreading ui-thread

在下面的代码中,我试图在单击按钮时运行一个线程。在按钮监听器中,我创建了一个新线程并运行它......但是在运行时,当按下按钮时,按钮本身卡住并且应用程序没有响应并且我收到 ANR 对话框。此外,当套接字连接成功时,即使 TexView

mtvStatus.setText("RFC-SOCKET CONNECTED");

什么都不显示。

请告诉我为什么会这样。

按钮监听器:

this.mbtnConnect.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            BluetoothSocket rfcSocket = mSPPCtrl.rfcConnect();
            if (rfcSocket.isConnected()) {
                mtvStatus.setText("RFC-SOCKET CONNECTED");

                Thread rx = new Thread(new RxRun(rfcSocket));
                rx.run();

            } else {
                mtvStatus.setText("RFC-SOCKET NOT CONNECTED");
            }

        }
    });

可运行类

private class RxRun implements Runnable {

    private BluetoothSocket mRFCSocket = null;
    private OutputStream mRFCOS = null;
    private InputStream mRFCIS = null;

    public RxRun(BluetoothSocket rfcSocket) {
        this.mRFCSocket = rfcSocket;

        try {
            this.mRFCOS = rfcSocket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            this.mRFCIS = rfcSocket.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            this.mRFCOS.write(DIRON.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }

        while (this.mRFCSocket.isConnected()) {
            try {
                int readBytes = this.mRFCIS.read(new byte[5120]);
                Log.d(TAG, CSubTag.bullet("RxRun", "readBytes:" + readBytes));
                //mtvRx.setText(""+readBytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

最佳答案

...when the button is pressed, the button itself freezes and the app does not respond and I receive ANR dialog. Moreover, when the socket is connected successfully even the TexView displays nothing.

这是预料之中的,因为您实际上还没有启动 rx 线程。这是正在发生的事情:

  1. mSPPCtrl 已连接,
  2. mtvStatus 的文本设置为 "RFC-SOCKET CONNECTED",但您无法直观地看到它,因为
  3. RxRun 实例的
  4. run() 方法被手动调用,其中循环 while (this.mRFCSocket.isConnected() ) 只要套接字已连接就可以持续。

以上所说的都是在UI线程上调用的,这就是ANR的原因。

您不应手动调用 run()。使用

启动rx线程
rx.start();

此外,我强烈建议将所有 rfcSocket 逻辑移动到线程内,并在连接成功/失败时通知 UI 线程。

编辑

这是我评论中提到的一个选项。

在单击按钮时启动 rx 线程

this.mbtnConnect.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        new Thread(new RxRun(rfcSocket)).start();
    }
});

将您的逻辑移动到 run() 方法中:

public void run() {
        BluetoothSocket rfcSocket = mSPPCtrl.rfcConnect();
        if (rfcSocket.isConnected()) {
            mtvStatus.post(new Runnable() {
                @Override
                public void run() {
                    mtvStatus.setText("RFC-SOCKET CONNECTED");
                }
            });
        } else {
            mtvStatus.post(new Runnable() {
                @Override
                public void run() {
                    mtvStatus.setText("RFC-SOCKET NOT CONNECTED");
                }
            });
            return;
        }
    // the rest of your logic
    }

一些可能有帮助的链接:

  1. 关于 Threads 的 Android 文档
  2. SO 问题 Android basics: running code in the UI thread
  3. 关于 Update UI from Thread 的另一篇 SO 帖子

关于java - 为什么 UI 线程被阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33677401/

相关文章:

c - 如何在 C 中创建两个同时运行的无限循环?

java - Ant: "IOException: Error writing request body to server"部署到 tomcat

java - 我可以使用 identityHashCode 在尊重相同性的对象之间生成 compareTo 吗?

java - javax.validation.ConstraintValidator 中的 Guice 多重绑定(bind)注入(inject)

android - 从 Android App 下载的文件在下载目录中不可见

android - 如何关闭安卓应用程序?

multithreading - Delphi - 在单次成功执行或用户取消后终止线程

java - 将多个值添加到 HashMap 中的一个键

android - 使用 FLAG_ACTIVITY_NO_HISTORY 和 startActivityForResult 在 Android 应用程序中导航

multithreading - 线程安全的 Web 应用程序 - 为什么它很重要?