Полагаю, это более общий вопрос, но моя программа на Android, кажется, вызывает onResume в основном потоке пользовательского интерфейса между этими двумя вызовами функций, связанных с созданием потока. Это вызывает другие вызовы, которые я не хочу выполнять, и до сих пор я нашел единственный способ обойти это - установить глобальные флаги (что мне не нравится, и, на мой взгляд, это плохая практика программирования). Это выглядит примерно так:
mConnectThread = new ConnectThread(bd);
mConnectThread.start();
Каким-то образом между этими вызовами (которые выполняются из потока пользовательского интерфейса объектом BluetoothCommHandler) вызывается onResume. Если бы кто-то мог указать мне на хороший источник того, когда onResume и другие события жизненного цикла активности запускаются, я был бы очень признателен. Кроме того, я проверил это: http://developer.android.com/reference/android/app/Activity.html, и, похоже, у меня не было подсказок, которые я мог бы найти.
Последнее замечание - onResume ВСЕГДА вызывается между этими двумя вызываемыми командами, и это заставляет меня думать, что на самом деле это не проблема переключения потоков.
Я также только что заметил, что onResume вызывается как пара onPause, который вызывается WAY раньше - все еще неясно, почему это происходит именно между этими двумя вызовами функций.
РЕДАКТИРОВАТЬ: Код включен ниже.
Вызов объекта-обработчика Bluetooth:
mBComm = new BluetoothCommHandler(this, mHandler);
Функция onResume в основном потоке пользовательского интерфейса (mNoRestartFlag
такова, что этот конкретный бит вызывается только тогда, когда я этого хочу. Это НЕ флаг, на который я ссылаюсь выше - он обрабатывает другой случай, о котором я здесь не говорю):
@Override
protected void onResume() {
super.onResume();
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent,
mFilters, mTechLists);
Log.i(TAG, "OnResume called.");
if(mBComm != null && !mNoRestartFlag) {
mBComm.start();
}
}
Объявление ActivityHandler (аналогично DeviceListActivity) в AndroidManifest (обратите внимание, что это действие в стиле Theme.Dialog, которое появляется поверх потока пользовательского интерфейса, вызывая onPause, о котором я говорил выше):
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.
Подводя итог , я создаю объект BluetoothCommHandler в потоке пользовательского интерфейса, он пытается создать ConnectThread, а затем при вызове команды accept () для разъема bluetooth происходит сбой, потому что функция cancel () поскольку поток был вызван (у которого просто есть try-catch, который закрывает сокет). Эта отмена вызывается из функции start (), которая перечислена выше, которая вызывается функцией onResume. OnResume является дополнением к onPause, который вызывается из-за диалогового окна селектора, появляющегося над основным действием пользовательского интерфейса. Этот onResume, кажется, всегда вызывается между первыми двумя строками кода, о которых я упоминал до РЕДАКТИРОВАНИЯ. Я пытаюсь выяснить, почему это всегда происходит именно ТАМ, чтобы я мог выполнить accept () без закрытия сокета.