#flutter #dart #stream #future
Вопрос:
Я хочу подключить свое приложение Flutter к устройству Bluetooth с помощью библиотеки flutter_blue и вернуть результат (что угодно), когда соединение включено. Но я не понимаю, как это сделать. Вот мой код :
Будущее подключение(устройство BLUETOOTH-устройства) асинхронно { _btDevice = устройство;
StreamSubscription<BluetoothDeviceState> subscription;
subscription = device.state.listen((event) async {
if (event != BluetoothDeviceState.connected) {
await device.connect();
} else {
await device.discoverServices().then((value) => _initFeatures(value));
}
})
..onDone(() {
// Cascade
print("onDone");
});
subscription.asFuture();
//subscription.cancel();
}
И когда я вызываю эту функцию с
await newDevice.connect(bluetoothDevice).then((value) => print('OK'));
«ОК» пишется перед реальным подключением. _initFeatures, если вы звоните, когда устройство подключено.
Я пытаюсь использовать asFuture из StreamSubscription с помощью onDone, но это ничего не меняет.
Не могли бы вы мне помочь, пожалуйста ?
ОБНОВЛЕНИЕ 12/10 Я работал над другим проектом в течение нескольких месяцев, и когда я возвращаюсь, я не могу решить проблему, поэтому я добавляю полный код. Концепция заключается в том, что виджет класса вызывает подключение будущего в другом классе и должен получить окончание работы.
Виджет
Future<void> _connectDevice() async {
try {
widget.device.connect(widget.btDevice!).then((value) => _initValue());
} catch (e) {
print(e);
}
}
_initValue () — это метод для создания остальной части экрана
и будущее соединяется()
Future connect(BluetoothDevice device) async {
_btDevice = device;
StreamSubscription<BluetoothDeviceState> subscription;
subscription = device.state.listen((event) async {
if (event != BluetoothDeviceState.connected) {
await device.connect();
} else {
await device
.discoverServices()
.then((value) => _initFeatures(value))
.then((value) => print("OK"));
}
});
await subscription.asFuture();
await subscription.cancel();
}
Чего бы я хотел, так это чтобы будущее заканчивалось, когда print("OK")
вызывается, в порядке .then((value) => _initValue());
вызова. Проблема только в этом конце. Возможно, это не самый лучший способ реализации такого рода решений.
Комментарии:
1. Я не знаком с тем, как
package:flutter_blue
предполагается использовать, ноStream.listen
ожидается, что 1.onData
обратный вызов вернетсяvoid
. Это означает, что его возвращаемое значение будет проигнорировано, поэтому, если вы передадите асинхронный обратный вызов, не будет прямого способа узнать, когда этот обратный вызов завершится. 2. Ваш пример вызываетsubscription.asFuture()
, но неawait
делает этого, поэтому ничто не будет ждать завершения подписки.2. Кроме того, это не обязательно проблема, но обычно непоследовательно использовать оба
await
иFuture.then
.await
это синтаксический сахар для созданияFuture.then
обратного вызова для вас. Просто используйawait
.3. Я знаю, что для нецелесообразности сочетать ожидание и затем, но иногда (например, с ShowDialog) кажется, что только ожидания недостаточно
4.Это поздно для игры, но, пожалуйста, обратите внимание, что StreamSubscription.listen перезаписывает обратные вызовы onDone и onError, поэтому вызов после прослушивания устраняет обратный вызов onDone, который вы определили в первой части вашего фрагмента
5. Наконец-то я нахожу решение. В
_connectDevice
я отправил обратный вызов в будущее, который является методом, который я хотел, чтобы мне перезвонили, и когда подписка на поток завершена, он запускает обратный вызов