我已经搜索了线程和looper之间的关系,我现在只知道这两个词的字面含义是什么。在达到特定条件时,我仍然有点困惑。
当我尝试构建一个关于与蓝牙设备通信的应用程序时,我遇到了这个问题。我在连接线程中遇到了问题。
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;
public ConnectThread(BluetoothDevice device, boolean secure) {
mmDevice = device;
BluetoothSocket tmp = null;
mSocketType = secure ? "Secure" : "Insecure";
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE);
}
} catch (IOException e) {
tip("Socket Type: " + mSocketType + "create() failed");
}
mmSocket = tmp;
}
public void run() {
Looper.prepare();
setName("ConnectThread" + mSocketType);
// Always cancel discovery because it will slow down a connection
if(mBluetoothAdapter.isDiscovering())
mBluetoothAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
e2.printStackTrace();
}
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothThreads.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice, mSocketType);
Looper.loop();
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
此代码是从Android Developers的示例下载的。而且我自己添加了Looper.prepare(),Looper.loop()。在调用这两种方法时,应用程序将崩溃。我收到了android studio的警告:无法在没有调用Looper.prepare()的线程内创建处理程序。这就是我添加这两种方法的原因。
我想问一下,我是否以正确的方式调用这两种方法?
为什么我必须在没有像其他人一样使用Toast或Handler时调用它们?
答案 0 :(得分:0)
我想问一下,我是否以正确的方式调用这两种方法?
是
为什么我必须在没有像其他人一样使用Toast或Handler时调用它们?
Looper.loop()
和Looper().prepare()
用于创建MessageQueue
并处理此MessageQueue
android建议使用Handler
,因此如果您使用Looper.loop()
然后你应该使用Looper.prepare()
。
答案 1 :(得分:0)
好吧,最后我弄清楚自己的项目有什么问题。 build.gradle没有任何关系,但是感谢 Android Dev 。
实际上这是我自己的责任。在示例项目BluetoothChat中,调用Log.d()
之类的方法来指示调试信息。但我不知道在哪里找到Log.d()
的结果,所以我用Toast
替换了它们。我觉得那很好。但我发现Toast
中不能使用ConnectThread
,否则会引发异常:
java.lang.RuntimeException:无法在未调用Looper.prepare()的线程内创建处理程序
我在方法Toast
中使用connectionFailed()
,这就是问题所在。
答案 2 :(得分:0)
实际上,不需要Looper.prepare()
和Looper.loop()
。只有当你想在线程中附加Handler
时才需要这些,在你的情况下,我看不到这样的要求。
基本上,一旦你调用Looper.prepare()
,它就会为这个线程分配一个消息队列,这样处理程序传递的所有后续消息都将以队列方式逐个处理。
注意:要进行调试,请始终使用Log.d()
/ Log.w()
/ Log.e()
并避免使用祝酒词。