Android: создание нового потока вызывает onResume? - PullRequest
1 голос
/ 21 марта 2011

Полагаю, это более общий вопрос, но моя программа на 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 () без закрытия сокета.

...