Оператор ожидания, который является последовательным - PullRequest
0 голосов
/ 05 марта 2020

У меня есть проблема, приводящая к требованию необходимости последовательно ждать перехода от одного к другому. В настоящее время я делаю это, устанавливая 3 runnables с различными задержками, чтобы позволить последовательному потоку данных появляться на моем соединении Bluetooth. Однако, хотя это работает, я чувствую, что должна быть лучшая / более чистая реализация этого. Мой текущий код приведен ниже.

Мой код работает следующим образом:

  • Команда записи 1
  • Дождитесь записи команды
  • Команда записи 2
  • Подождите, пока команда будет написана
  • Введите команду 3
  • Подождите, пока команда будет написана

Пожалуйста, не могли бы вы дать мне несколько советов о том, как Я могу выполнять свои функции записи одну за другой в лучшем виде.

Handler h =new Handler() ;
h.postDelayed(new Runnable() {
    public void run() {
        Log.d(TAG, "Write 1");
        mBluetoothLeService.writeCharacteristic(10);
    }
}, 1000);

Handler h1 =new Handler() ;
final int Command_to_run = value;
h1.postDelayed(new Runnable() {
    public void run() {
        Log.d(TAG, "Write 2");
        mBluetoothLeService.writeCharacteristic(Command_to_run);
    }
}, 2000);

Handler h2 =new Handler() ;
h2.postDelayed(new Runnable() {
    public void run() {
        Log.d(TAG, "Write 3");
        mBluetoothLeService.writeCharacteristic(20);
    }
}, 3000);

Код записи

 public void writeCharacteristic(int Data) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }

        byte[] value = intToByteArray(Data);

        BluetoothGattService mCustomService = 
        mBluetoothGatt.getService(UUID.fromString("f3641400-00b0-4240-ba50- 
        05ca45bf8abc"));
        if(mCustomService == null){
            Log.w(TAG, "Custom BLE Service not found");
            return;
        }
        /*get the read characteristic from the service*/
        BluetoothGattCharacteristic characteristic = 
        mCustomService.getCharacteristic(UUID.fromString("f3641401-00b0-4240- 
        ba50-05ca45bf8abc"));
        characteristic.setValue(value);
        mBluetoothGatt.writeCharacteristic(characteristic);
    }

Ответы [ 3 ]

1 голос
/ 10 марта 2020

Я думаю, что mBluetoothLeService.writeCharacteristic(10); вызовы, подобные этим, уже блокируют поток, поэтому их использование в порядке без необходимости в обработчиках может быть вашим решением. Я не думаю, что эта функция является асинхронной, поэтому, если она возвращает true, вы можете написать следующую. Они являются булевыми функциями, поэтому, если он возвращает true, вы можете переключиться на следующую.

Я изучил исходный код, и если он выдает исключение внутри, он возвращает false. В противном случае он возвращает, был ли он успешным или нет.

Примечание: это поведение может отличаться в разных версиях API, исходный код, на который я обращался, был для API 29. Хотя я считаю, что поведение будет то же самое, за исключением того, что вам может понадобиться обернуть вызовы mBluetoothLeService.writeCharacteristic(10); в блок try-catch.

Мне нужно отредактировать это, так как ответ неверный, логического возвращаемого значения недостаточно, чтобы определить была ли операция успешной. Операция действительно асинхронная, но есть обратный вызов, который вы можете использовать ( этот обратный вызов ), чтобы проверить, была ли операция записи успешной, а затем перейти к следующей.

Проверка этот ответ для получения дополнительной информации, и, если возможно, уберите галочку с этого, пожалуйста.

1 голос
/ 05 апреля 2020
* BLE API

Android полностью асинхронный и нет методов блокировки. Методы вернут истину, если операция была инициирована успешно, и ложь в противном случае. В частности, false будет возвращено, если уже выполняется операция.

При вызове requestMtu, writeCharacteristic, readCharacteristic и т. Д. Соответствующий обратный вызов onMtuChanged, onCharacteristicWrite, onCharacteristicRead будет вызвано после завершения операции. Обратите внимание, что обычно это означает, что туда и обратно на удаленное устройство может потребоваться разное время, в зависимости от того, насколько шумна среда и какие параметры подключения у вас есть, поэтому никогда не бывает хорошей идеей спать или задерживать некоторое фиксированное количество времени. время и предположим, что операция завершена.

Чтобы сделать структуру кода немного лучше и избежать «ада обратного вызова», вы можете, например, реализовать (потокобезопасную) очередь GATT, которая позже используется вашим применение. Таким образом, вы можете просто набрать то, что вы хотите в очереди, и позволить вашей библиотеке очереди GATT обрабатывать грязные вещи. Или вы можете использовать некоторую библиотеку Android BLE, которая уже делает это.

См. https://medium.com/@martijn.van.welie / making- android -ble-work-part-3-117d3a8aee23 для получения дополнительной информации. тщательное обсуждение.

0 голосов
/ 05 марта 2020

Если работа, которую вы хотите выполнить последовательно, может выполняться асинхронно, вы можете рассмотреть новый WorkManager, включенный в Android Jetpack. С WorkManager вы можете очень грамотно организовать всю свою работу, в соответствии с документацией вы можете сделать это следующим образом:

WorkManager.getInstance(myContext)
   // Candidates to run in parallel
   .beginWith(listOf(filter1, filter2, filter3))
   // Dependent work (only runs after all previous work in chain)
   .then(compress)
   .then(upload)
   // Don't forget to enqueue()
   .enqueue()

Библиотека позаботится о порядке выполнения для вас. Вы можете найти больше информации по этому вопросу здесь: https://developer.android.com/topic/libraries/architecture/workmanager/how-to/chain-work

...