为什么 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");
}
}
});
运行启用class
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
线程。这是正在发生的事情:
mSPPCtrl
已连接,
mtvStatus
的文本设置为"RFC-SOCKET CONNECTED"
,但您无法直观地看到它,因为
RxRun
实例的 run()
方法被手动调用 其中循环 while (this.mRFCSocket.isConnected())
可能会持续到套接字已连接。
上面所说的都是在UI
线程上调用的,这就是ANR
的原因。
您不应手动调用 run()
。使用
启动 rx
线程
rx.start();
此外,我强烈建议将所有 rfcSocket
逻辑移动到线程内,并通知 success/failure 上的 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 关于 Threads
的文档
- SO问题Android basics: running code in the UI thread
- Update UI from Thread
上的另一个 SO post
这里的错误很简单 - 不要在 Thread 实例上使用 run()
,因为这实际上 运行 它在当前 Thread 上是可运行的!使用 start()
它将正常工作:-)
在下面的代码中,我试图在单击按钮时 运行 一个线程。在按钮侦听器中,我创建了一个新线程并 运行 它...但是在 运行 时间,当按下按钮时,按钮本身冻结并且应用程序没有响应并且我收到 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");
}
}
});
运行启用class
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 theTexView
displays nothing.
这是预料之中的,因为您实际上还没有启动 rx
线程。这是正在发生的事情:
mSPPCtrl
已连接,mtvStatus
的文本设置为"RFC-SOCKET CONNECTED"
,但您无法直观地看到它,因为run()
方法被手动调用 其中循环while (this.mRFCSocket.isConnected())
可能会持续到套接字已连接。
RxRun
实例的 上面所说的都是在UI
线程上调用的,这就是ANR
的原因。
您不应手动调用 run()
。使用
rx
线程
rx.start();
此外,我强烈建议将所有 rfcSocket
逻辑移动到线程内,并通知 success/failure 上的 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 关于 Threads 的文档
- SO问题Android basics: running code in the UI thread
- Update UI from Thread 上的另一个 SO post
这里的错误很简单 - 不要在 Thread 实例上使用 run()
,因为这实际上 运行 它在当前 Thread 上是可运行的!使用 start()
它将正常工作:-)