Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/188.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么UI线程被阻塞?_Java_Android_Multithreading_Ui Thread - Fatal编程技术网

Java 为什么UI线程被阻塞?

Java 为什么UI线程被阻塞?,java,android,multithreading,ui-thread,Java,Android,Multithreading,Ui Thread,在下面的代码中,我试图在单击按钮时运行线程。在按钮侦听器中,我创建了一个新线程并运行它…但是在运行时,当按下按钮时,按钮本身冻结,应用程序不响应,我收到ANR对话框。此外,当插座成功连接时,即使是TexView mtvStatus.setText("RFC-SOCKET CONNECTED"); 不显示任何内容 请让我知道为什么会发生这种情况 按钮侦听器: this.mbtnConnect.setOnClickListener(new View.OnClickListener() {

在下面的代码中,我试图在单击按钮时运行线程。在按钮侦听器中,我创建了一个新线程并运行它…但是在运行时,当按下按钮时,按钮本身冻结,应用程序不响应,我收到
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
线程。下面是正在发生的事情:

  • mSPPCtrl
    已连接
  • mtvStatus
    的文本设置为
    “RFC-SOCKET CONNECTED”
    ,但您无法直观地看到它,因为
  • 手动调用
    RxRun
    实例的
    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
        }
    
    一些可能有帮助的链接:

  • 关于Android的文档
  • 那么问题
  • 另一个如此的帖子

  • 这里的错误非常简单-不要在线程实例上使用
    run()
    ,因为这实际上会在当前线程上运行它!使用
    start()
    它会工作得很好:-)

    我认为你不应该调用rx.run(),而应该调用rx.start();您应该使用
    rx.start()而不是
    rx.run()也不要认为您应该在UI线程上执行.rfConnect()…或者为什么不应该直接使用
    线程
    。改用
    执行器服务
    .run()
    方法继承自
    Runnable
    ,不会自动在“后台”运行。另外,你打算如何收集结果?@fge我只是在做一个测试。为了回答你的问题“你打算如何收集结果”。。我想在while循环内的log.d中显示结果。但是它不显示任何内容,并且在这一行之后显示任何日志语句:int readBytes=this.mRFCIS.read(new byte[5120]);从来没有被调用过…任何建议为什么没有被调用谢谢你的回答你能告诉我更多关于notify()方法为什么应该使用它吗它像“return”@LetsamrIt不,我不是指
    对象的
    notify()
    方法,我把它用作动词。有几个选项可以从后台线程“通知”UI线程。类似于通过
    处理程序
    runOnUiThread()
    方法,如果您将上下文传递给后台线程,
    观察者
    模式实现或直接调用
    您的活动
    方法(其中视图必须仅在UI线程上接触)。只需使用其中一种技术。如果你在这方面真的需要帮助,我明天会编辑答案(我几乎睡着了…:)