繁体   English   中英

为什么UI线程被阻止?

[英]Why the UI thread is getting blocked?

在下面的代码中,我试图在单击按钮时运行一个线程。 在按钮监听器中,我创建一个新线程并运行它...但是在运行时,按下按钮时,按钮本身会冻结,应用程序不响应,我收到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();
            }
        }

    }
}

...当按下按钮时,按钮本身冻结,应用程序没有响应,我收到ANR对话框。 而且,当插座连接成功时,即使TexView显示任何内容。

这是预期的,因为你还没有真正启动rx线程。 这是正在发生的事情:

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

所有上述内容都是在UI -thread上调用的,这就是ANR的原因。

你不应该手动调用run() 用。启动rx线程

rx.start();

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

编辑

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

单击按钮启动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. 关于线程的 Android文档
  2. 所以问题Android基础知识:在UI线程中运行代码
  3. 来自Thread的更新UI上的另一个SO帖子

这里的错误非常简单 - 不要在Thread实例上使用run() ,因为这实际上会在当前Thread上运行它的Runnable 使用start() ,它会正常工作:-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM