我想这是一个更通用的问题,但我的Android程序似乎在这两个与线程创建相关的函数调用之间的主UI线程中调用onResume。这会导致我不希望发生的其他调用,到目前为止,我发现的唯一方法就是设置全局标志(我不喜欢这种标志,并且在我看来是糟糕的编程习惯)。看起来很像这样:
mConnectThread = new ConnectThread(bd);
mConnectThread.start();
不知何故,在这些调用之间(由BluetoothCommHandler对象从UI线程创建),onResume被调用。如果有人能指出我在onResume和其他活动生命周期事件被触发时的良好来源,我将非常感激。此外,我检查了这个:http://developer.android.com/reference/android/app/Activity.html,它似乎没有任何我能找到的提示。
最后一点 - 在调用这两个命令之间调用onResume ALWAYS,这让我觉得它不是一个真正的线程切换问题。
我还注意到onResume被调用为一对onPause,之前被称为WAY - 但仍然不知道为什么它恰好在这两个函数调用之间发生。
编辑:代码包含在下方。
调用蓝牙处理程序对象:
mBComm = new BluetoothCommHandler(this, mHandler);
主UI线程中的onResume函数(mNoRestartFlag
是这样,只有当我想要它时才会调用这个特定的位。它是 NOT 我上面提到的标志 - 它处理另一个我不在这里谈论的案例):
@Override
protected void onResume() {
super.onResume();
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent,
mFilters, mTechLists);
Log.i(TAG, "OnResume called.");
if(mBComm != null && !mNoRestartFlag) {
mBComm.start();
}
}
AndroidManifest中的activity android:name=".OptionsHandler"
android:label="@string/select_device"
android:theme="@android:style/Theme.Dialog"
android:configChanges="orientation|keyboardHidden" />
创建实际的connectThread:
public synchronized void connect(BluetoothDevice bd) {
Log.i(TAG, "connect called from inside BluetoothCommHandler");
if (mAcceptThread == null) {
Log.i(TAG, "Creating an AcceptThread");
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
mConnectThread = new ConnectThread(bd);
mConnectThread.start();
}
创建和运行ConnectThread(mDontKill
标志 IS 我上面提到的用于绕过onResume症状的标志):
public ConnectThread(BluetoothDevice bd) {
Log.i(TAG, "created ConnectThread");
mBD = bd;
BluetoothSocket bs = null;
try {
bs = mBD.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.i(TAG, "Could not create an RFCOMM socket!", e);
}
mBS = bs;
if (mBS != null) Log.i(TAG, "BluetoothSocket acquired");
else Log.i(TAG, "BluetoothSocket null!");
mDontKillFlag = true;
}
public void run() {
Log.i(TAG, "BEGIN ConnectThread");
// Always cancel discovery because it will slow down a connection
mBluetoothAdapter.cancelDiscovery();
mDontKillFlag = false;
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mBS.connect();
Log.i(TAG, "Connected to BluetoothDevice");
} catch (IOException e) {
Log.i(TAG, e.toString());
// Close the socket
try {
mBS.close();
} catch (IOException e2) {
Log.i(TAG, "unable to close RFCOMM socket", e2);
}
Log.i(TAG, "About to call connectionFailed");
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothCommHandler.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mBS, mBD);
}
导致问题的实际start()函数:
public synchronized void start() {
if (D) Log.i(TAG, "start called from inside BluetoothCommHandler");
// Cancel any thread attempting to make a connection
if (mConnectThread != null && !mDontKillFlag)
{mConnectThread.cancel(); mConnectThread = null;}
// Cancel any thread currently running a connection
if (mConnectedThread != null)
{mConnectedThread.cancel(); mConnectedThread = null;}
if (mAcceptThread == null) {
Log.i(TAG, "Creating an AcceptThread");
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
}
图例: mBS
是BluetoothSocket的成员变量,mDB
是BluetoothDevice的成员变量。
总结一下,我在UI线程上创建一个BluetoothCommHandler对象,这会尝试创建一个ConnectThread,然后在蓝牙套接字上调用accept()命令时,它会因为cancel()而失败已经调用了线程的函数(它只是有一个关闭套接字的try-catch)。从上面列出的start()函数调用此取消,该函数由onResume函数调用。 onResume是因为在主UI活动上出现选择器对话框而被调用的onPause的补充。这个onResume似乎总是被我在编辑之前提到的前两行代码之间调用。我试图弄清楚为什么它总是恰好发生在那里,所以我可以在没有套接字被关闭的情况下发生一个accept()。