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
}
一些可能有帮助的链接:
这里的错误非常简单-不要在线程实例上使用
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线程上接触)。只需使用其中一种技术。如果你在这方面真的需要帮助,我明天会编辑答案(我几乎睡着了…:)