Flutter Bloc A 在 Bloc B 中添加流,但该流不会通过 StreamBuilder 在 UI 中呈现
Flutter Bloc A adds stream in Bloc B but this stream will not render in UI via StreamBuilder
我正在尝试为一个新的 flutter 项目转向 bloc/provider 架构。一段时间以来,我一直在解决一个问题,其中一个集团的流将通过 StreamBuilder 在 UI 上呈现,但另一个集团不会。在继续之前,我很想(也需要)了解原因。
我有两个集团,第一个集团是ble_service。我可以从 UI 调用函数到这个集团(app.dart 行 60-72)连接到设备并通过 StreamBuilder 呈现 UI 中的特征 returns(行98).只需在 UI 中渲染从 ble 设备返回的 json 负载。这更新非常频繁,每秒多次。
我的计划是拥有一个解析器块 (bleBeltNotifyParser_bloc),它将解析来自 ble_service 的传入 json 有效负载,然后从那里 UI 流式传输。在 ble_service 中,我将 json 有效负载传递到 parserInputSink,这是来自 Parser Bloc 的流(ble_service 第 99 行)。在 bleBeltNotifyParser.bloc 中,我在第 21 行收听它并将其传递给我计划解析它的 aTest2()。我在这里停下来是因为我试图在 UI(app.dart 行 108)上呈现此数据,但无论将数据传递到 parserInputController 的不同组合如何,UI 仅呈现种子数据。我通过在第 28 行打印它来确认流正在获取数据。
我还确认我可以通过按钮(第 73 和 80 行)非常简单地将一些数据放入流中,从而从 UI 到达解析器集团。按下这些按钮时,该数据将添加到流中,并且 UI 按预期更新。
为什么 StreamBuilder 适用于 blue_service 而不是 bleBeltNotifyParser_bloc?我还尝试在服务中创建流,然后在解析器中收听它。他们也不走运。
我的main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
/// Starting here, everything is used regardless of dependencies
var blocProvider = BlocProvider(
bleBeltNotifyParserBloc: BleBeltNotifyParserBloc(),
bleService: BleService(),
);
runApp(
AppStateContainer(
blocProvider: blocProvider,
child: App(),
),
);
}
我的 AppState
import 'package:flutter/material.dart';
import 'package:flutterappbelt3/main.dart';
import 'package:flutterappbelt3/blocs/ble_service.dart';
import 'package:flutterappbelt3/blocs/bleBeltNotifyParser_bloc.dart';
class AppStateContainer extends StatefulWidget {
final Widget child;
final BlocProvider blocProvider;
const AppStateContainer({
Key key,
@required this.child,
@required this.blocProvider,
}) : super(key: key);
@override
State<StatefulWidget> createState() => AppState();
static AppState of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(_AppStoreContainer) as _AppStoreContainer).appData;
}
}
class AppState extends State<AppStateContainer> {
BlocProvider get blocProvider => widget.blocProvider;
@override
Widget build(BuildContext context) {
return _AppStoreContainer(
appData: this,
blocProvider: widget.blocProvider,
child: widget.child,
);
}
void dispose() {
super.dispose();
}
}
class _AppStoreContainer extends InheritedWidget {
final AppState appData;
final BlocProvider blocProvider;
_AppStoreContainer({
Key key,
@required this.appData,
@required child,
@required this.blocProvider,
}) : super(key: key, child: child);
@override
bool updateShouldNotify(_AppStoreContainer oldWidget) => oldWidget.appData != this.appData;
}
class BlocProvider {
BleBeltNotifyParserBloc bleBeltNotifyParserBloc = BleBeltNotifyParserBloc();
BleService bleService;
BlocProvider({
@required this.bleBeltNotifyParserBloc,
@required this.bleService,
});
}
我的app.dart
import 'package:flutter/material.dart';
import 'package:flutterappbelt3/blocs/bleBeltNotifyParser_bloc.dart';
import 'blocs/app_state.dart';
import 'blocs/ble_service.dart';
class App extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Position App',
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: PositionApp(),
);
}
}
class PositionApp extends StatefulWidget {
@override
_PositionAppState createState() => _PositionAppState();
}
class _PositionAppState extends State<PositionApp> {
BleService _service = BleService();
BleBeltNotifyParserBloc _bloc = BleBeltNotifyParserBloc();
@override
void initState() {
super.initState();
//_service.startScan();
//_service.bleNotifyFromBelt.listen((String data) {_bloc.parserInputSink.add(data);});
}
@override
Widget build(BuildContext context) {
//SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
BleService _bleServiceBloc = AppStateContainer.of(context).blocProvider.bleService;
BleBeltNotifyParserBloc _bleBeltNotifyParserBloc = AppStateContainer.of(context).blocProvider.bleBeltNotifyParserBloc;
return Scaffold(
appBar: AppBar(
title: Text("Position"),
),
body: Center(
child: Column(
children: <Widget>[
Container(
child: Text("hello"),
),
Container(
child: FlatButton(onPressed: () {
_bleServiceBloc.startScan();
},
child: Text("Scan & Connect"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleServiceBloc.discoverServices();
},
child: Text("discover services"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleServiceBloc.disconnectFromDevice();
},
child: Text("disconnect"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleBeltNotifyParserBloc.addToParserController1();
},
child: Text("Parser One"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleBeltNotifyParserBloc.addToParserController2();
},
child: Text("Parser Two"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleBeltNotifyParserBloc.aTest();
},
child: Text("aTest"),
),
),
Container(
child: StreamBuilder(
initialData: "0",
stream: _bleServiceBloc.bleNotifyFromBelt,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.data == null) return CircularProgressIndicator();
else return Text(
snapshot.data.toString(),
style: TextStyle(fontSize: 14.0, color: Colors.black),
textAlign: TextAlign.center,
);}
),
),
Container(
child: StreamBuilder(
initialData: "0",
stream: _bleServiceBloc.bleStatusFromBelt,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.data == null) return CircularProgressIndicator();
else return Text(
snapshot.data.toString(),
style: TextStyle(fontSize: 14.0, color: Colors.black),
textAlign: TextAlign.center,
);}
),
),
],
),
),
);
}
}
我的ble_service.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'dart:convert' show utf8;
import 'package:rxdart/rxdart.dart';
import 'package:flutterappbelt3/blocs/bleBeltNotifyParser_bloc.dart';
class BleService {
//BleBeltNotifyParserBloc _bloc = BleBeltNotifyParserBloc();
final String TARGET_DEVICE_NAME = "ESP32";
final String SERVICE_UUID = "4fafc201-1fb5-459e-8fcc-c5c9c331914b";
final String NOTIFY_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8";
final String WRITE_UUID = "724b0547-3747-4c00-9710-5305a020018f";
FlutterBlue flutterBlue = FlutterBlue.instance;
StreamSubscription<ScanResult> scanSubScription;
BluetoothDevice beltDevice;
BluetoothCharacteristic characteristicNotify;
BluetoothCharacteristic characteristicWrite;
String bleNotifyString = "";
BleBeltNotifyParserBloc _bloc = BleBeltNotifyParserBloc();
BehaviorSubject<String> _bleStatusFromBeltController = BehaviorSubject<String>.seeded("BLE STATUS");
Stream<String> get bleStatusFromBelt => _bleStatusFromBeltController.stream;
StreamController<String> _bleNotifyFromBeltController = BehaviorSubject<String>.seeded("BLE NOTIFY");
Stream<String> get bleNotifyFromBelt => _bleNotifyFromBeltController.stream;
Sink<String> get bleNotifyFromBeltSink => _bleNotifyFromBeltController.sink;
BleService();
dispose() {
_bleStatusFromBeltController.close();
_bleNotifyFromBeltController.close();
}
startScan() {
//stopScan();
// // SCANNING
scanSubScription = flutterBlue.scan().listen((scanResult) async {
if (scanResult.device.name == TARGET_DEVICE_NAME) {
stopScan();
// // FOUND
beltDevice = await Future.value(scanResult.device).timeout(const Duration(seconds: 3));
connectToDevice();
}
}, onDone: () => stopScan());
}
stopScan() {
flutterBlue.stopScan();
scanSubScription?.cancel();
scanSubScription = null;
_bleStatusFromBeltController.add("Disconnected");
print("print Disconnected");
}
connectToDevice() async {
if (beltDevice == null) return;
// CONNECTING
await beltDevice.connect();
beltDevice.requestMtu(185);
print('print DEVICE CONNECTED');
print(" print BeltDevice $beltDevice");
_bleStatusFromBeltController.add("Connected");
print("print Connected");
//discoverServices();
}
discoverServices() async {
print("discoverServices beltDevice name is $beltDevice");
if (beltDevice == null) return;
List<BluetoothService> services = await beltDevice.discoverServices();
services.forEach((service) {
// do something with service
if (service.uuid.toString() == SERVICE_UUID) {
service.characteristics.forEach((characteristic) {
// set up notify characteristic
print("Service Found for $characteristic");
if (characteristic.uuid.toString() == NOTIFY_UUID) {
characteristicNotify = characteristic;
// tell characteristic on server to notify
characteristicNotify.setNotifyValue(true);
print("notify set to true");
// listen, convert and put notify value in stream
characteristicNotify.value.listen((value) {
bleNotifyString = utf8.decode(value);
//print("got characteristic $value");
print(bleNotifyString);
_bleNotifyFromBeltController.sink.add(bleNotifyString);
_bloc.parserInputSink.add(bleNotifyString);
});
// COMMUNICATING
}
// Prepares characteristic for Write
if (characteristic.uuid.toString() == WRITE_UUID) {
characteristicWrite = characteristic;
}
});
}
});
}
disconnectFromDevice() {
//if (beltDevice == null) return;
//stopScan();
beltDevice.disconnect();
_bleStatusFromBeltController.add("Disconnect");
print("Disconnect");
// DISCONNECTED
}
}
我的bleBeltNotifyParser_bloc
我无法渲染
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
import 'dart:math' as Math;
import 'package:flutterappbelt3/blocs/ble_service.dart';
class BleBeltNotifyParserBloc{
// final BleService _bloc = BleService();
StreamController<String> _parserInputController = BehaviorSubject<String>.seeded("Parser Input");
Stream<String> get parserInput => _parserInputController.stream;
Sink<String> get parserInputSink => _parserInputController.sink;
BleBeltNotifyParserBloc(){
_parserInputController.stream.listen(_aTest2);
//_bloc.bleNotifyFromBelt.listen((String data) {parserInputSink.add(data); print('Got eem! Input Parser $data');}); Tried various things - such as listening to streams originating from ble_service.
}
void _aTest2(data) {
print("WHAT!!! $data");
}
void aTest() {
//_bloc.bleNotifyFromBelt.listen((String data) {_parserInputController.sink.add(data);});
}
void addToParserController1() {
_parserInputController.sink.add("One");
}
void addToParserController2() {
_parserInputController.sink.add("Two");
}
dispose() {
_parserInputController.close();
}
}
我不想让这个问题无人回答,所以我想指出这个问题的答案在我发布的另一个问题的答案中。
来自已回答问题的评论涉及此问题。
I read it but I don't fully understand the problem (you made a lot of changes to test the stream that I don't know what was the real issue without the tests) but I saw you did the same thing by creating a BleBeltNotifyParserBloc called _bloc inside BleService, and I believe that was the reason it didn't update the UI (for the same reason it didn't work here).
在这个例子中,我正在尝试使用流的继承 Widget/Bloc 架构,然后将另一个问题移至 Provider/Bloc/Async 模型,以尝试弄清楚为什么 UI 在以下时间未更新将数据从 BleService 集团发送到 NotifyParser 集团。
我要感谢 https://whosebug.com/users/3547212/edwynzn 对链接问题的回答!!
我正在尝试为一个新的 flutter 项目转向 bloc/provider 架构。一段时间以来,我一直在解决一个问题,其中一个集团的流将通过 StreamBuilder 在 UI 上呈现,但另一个集团不会。在继续之前,我很想(也需要)了解原因。
我有两个集团,第一个集团是ble_service。我可以从 UI 调用函数到这个集团(app.dart 行 60-72)连接到设备并通过 StreamBuilder 呈现 UI 中的特征 returns(行98).只需在 UI 中渲染从 ble 设备返回的 json 负载。这更新非常频繁,每秒多次。
我的计划是拥有一个解析器块 (bleBeltNotifyParser_bloc),它将解析来自 ble_service 的传入 json 有效负载,然后从那里 UI 流式传输。在 ble_service 中,我将 json 有效负载传递到 parserInputSink,这是来自 Parser Bloc 的流(ble_service 第 99 行)。在 bleBeltNotifyParser.bloc 中,我在第 21 行收听它并将其传递给我计划解析它的 aTest2()。我在这里停下来是因为我试图在 UI(app.dart 行 108)上呈现此数据,但无论将数据传递到 parserInputController 的不同组合如何,UI 仅呈现种子数据。我通过在第 28 行打印它来确认流正在获取数据。
我还确认我可以通过按钮(第 73 和 80 行)非常简单地将一些数据放入流中,从而从 UI 到达解析器集团。按下这些按钮时,该数据将添加到流中,并且 UI 按预期更新。
为什么 StreamBuilder 适用于 blue_service 而不是 bleBeltNotifyParser_bloc?我还尝试在服务中创建流,然后在解析器中收听它。他们也不走运。
我的main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
/// Starting here, everything is used regardless of dependencies
var blocProvider = BlocProvider(
bleBeltNotifyParserBloc: BleBeltNotifyParserBloc(),
bleService: BleService(),
);
runApp(
AppStateContainer(
blocProvider: blocProvider,
child: App(),
),
);
}
我的 AppState
import 'package:flutter/material.dart';
import 'package:flutterappbelt3/main.dart';
import 'package:flutterappbelt3/blocs/ble_service.dart';
import 'package:flutterappbelt3/blocs/bleBeltNotifyParser_bloc.dart';
class AppStateContainer extends StatefulWidget {
final Widget child;
final BlocProvider blocProvider;
const AppStateContainer({
Key key,
@required this.child,
@required this.blocProvider,
}) : super(key: key);
@override
State<StatefulWidget> createState() => AppState();
static AppState of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(_AppStoreContainer) as _AppStoreContainer).appData;
}
}
class AppState extends State<AppStateContainer> {
BlocProvider get blocProvider => widget.blocProvider;
@override
Widget build(BuildContext context) {
return _AppStoreContainer(
appData: this,
blocProvider: widget.blocProvider,
child: widget.child,
);
}
void dispose() {
super.dispose();
}
}
class _AppStoreContainer extends InheritedWidget {
final AppState appData;
final BlocProvider blocProvider;
_AppStoreContainer({
Key key,
@required this.appData,
@required child,
@required this.blocProvider,
}) : super(key: key, child: child);
@override
bool updateShouldNotify(_AppStoreContainer oldWidget) => oldWidget.appData != this.appData;
}
class BlocProvider {
BleBeltNotifyParserBloc bleBeltNotifyParserBloc = BleBeltNotifyParserBloc();
BleService bleService;
BlocProvider({
@required this.bleBeltNotifyParserBloc,
@required this.bleService,
});
}
我的app.dart
import 'package:flutter/material.dart';
import 'package:flutterappbelt3/blocs/bleBeltNotifyParser_bloc.dart';
import 'blocs/app_state.dart';
import 'blocs/ble_service.dart';
class App extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Position App',
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: PositionApp(),
);
}
}
class PositionApp extends StatefulWidget {
@override
_PositionAppState createState() => _PositionAppState();
}
class _PositionAppState extends State<PositionApp> {
BleService _service = BleService();
BleBeltNotifyParserBloc _bloc = BleBeltNotifyParserBloc();
@override
void initState() {
super.initState();
//_service.startScan();
//_service.bleNotifyFromBelt.listen((String data) {_bloc.parserInputSink.add(data);});
}
@override
Widget build(BuildContext context) {
//SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
BleService _bleServiceBloc = AppStateContainer.of(context).blocProvider.bleService;
BleBeltNotifyParserBloc _bleBeltNotifyParserBloc = AppStateContainer.of(context).blocProvider.bleBeltNotifyParserBloc;
return Scaffold(
appBar: AppBar(
title: Text("Position"),
),
body: Center(
child: Column(
children: <Widget>[
Container(
child: Text("hello"),
),
Container(
child: FlatButton(onPressed: () {
_bleServiceBloc.startScan();
},
child: Text("Scan & Connect"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleServiceBloc.discoverServices();
},
child: Text("discover services"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleServiceBloc.disconnectFromDevice();
},
child: Text("disconnect"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleBeltNotifyParserBloc.addToParserController1();
},
child: Text("Parser One"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleBeltNotifyParserBloc.addToParserController2();
},
child: Text("Parser Two"),
),
),
Container(
child: FlatButton(onPressed: () {
_bleBeltNotifyParserBloc.aTest();
},
child: Text("aTest"),
),
),
Container(
child: StreamBuilder(
initialData: "0",
stream: _bleServiceBloc.bleNotifyFromBelt,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.data == null) return CircularProgressIndicator();
else return Text(
snapshot.data.toString(),
style: TextStyle(fontSize: 14.0, color: Colors.black),
textAlign: TextAlign.center,
);}
),
),
Container(
child: StreamBuilder(
initialData: "0",
stream: _bleServiceBloc.bleStatusFromBelt,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.data == null) return CircularProgressIndicator();
else return Text(
snapshot.data.toString(),
style: TextStyle(fontSize: 14.0, color: Colors.black),
textAlign: TextAlign.center,
);}
),
),
],
),
),
);
}
}
我的ble_service.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'dart:convert' show utf8;
import 'package:rxdart/rxdart.dart';
import 'package:flutterappbelt3/blocs/bleBeltNotifyParser_bloc.dart';
class BleService {
//BleBeltNotifyParserBloc _bloc = BleBeltNotifyParserBloc();
final String TARGET_DEVICE_NAME = "ESP32";
final String SERVICE_UUID = "4fafc201-1fb5-459e-8fcc-c5c9c331914b";
final String NOTIFY_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8";
final String WRITE_UUID = "724b0547-3747-4c00-9710-5305a020018f";
FlutterBlue flutterBlue = FlutterBlue.instance;
StreamSubscription<ScanResult> scanSubScription;
BluetoothDevice beltDevice;
BluetoothCharacteristic characteristicNotify;
BluetoothCharacteristic characteristicWrite;
String bleNotifyString = "";
BleBeltNotifyParserBloc _bloc = BleBeltNotifyParserBloc();
BehaviorSubject<String> _bleStatusFromBeltController = BehaviorSubject<String>.seeded("BLE STATUS");
Stream<String> get bleStatusFromBelt => _bleStatusFromBeltController.stream;
StreamController<String> _bleNotifyFromBeltController = BehaviorSubject<String>.seeded("BLE NOTIFY");
Stream<String> get bleNotifyFromBelt => _bleNotifyFromBeltController.stream;
Sink<String> get bleNotifyFromBeltSink => _bleNotifyFromBeltController.sink;
BleService();
dispose() {
_bleStatusFromBeltController.close();
_bleNotifyFromBeltController.close();
}
startScan() {
//stopScan();
// // SCANNING
scanSubScription = flutterBlue.scan().listen((scanResult) async {
if (scanResult.device.name == TARGET_DEVICE_NAME) {
stopScan();
// // FOUND
beltDevice = await Future.value(scanResult.device).timeout(const Duration(seconds: 3));
connectToDevice();
}
}, onDone: () => stopScan());
}
stopScan() {
flutterBlue.stopScan();
scanSubScription?.cancel();
scanSubScription = null;
_bleStatusFromBeltController.add("Disconnected");
print("print Disconnected");
}
connectToDevice() async {
if (beltDevice == null) return;
// CONNECTING
await beltDevice.connect();
beltDevice.requestMtu(185);
print('print DEVICE CONNECTED');
print(" print BeltDevice $beltDevice");
_bleStatusFromBeltController.add("Connected");
print("print Connected");
//discoverServices();
}
discoverServices() async {
print("discoverServices beltDevice name is $beltDevice");
if (beltDevice == null) return;
List<BluetoothService> services = await beltDevice.discoverServices();
services.forEach((service) {
// do something with service
if (service.uuid.toString() == SERVICE_UUID) {
service.characteristics.forEach((characteristic) {
// set up notify characteristic
print("Service Found for $characteristic");
if (characteristic.uuid.toString() == NOTIFY_UUID) {
characteristicNotify = characteristic;
// tell characteristic on server to notify
characteristicNotify.setNotifyValue(true);
print("notify set to true");
// listen, convert and put notify value in stream
characteristicNotify.value.listen((value) {
bleNotifyString = utf8.decode(value);
//print("got characteristic $value");
print(bleNotifyString);
_bleNotifyFromBeltController.sink.add(bleNotifyString);
_bloc.parserInputSink.add(bleNotifyString);
});
// COMMUNICATING
}
// Prepares characteristic for Write
if (characteristic.uuid.toString() == WRITE_UUID) {
characteristicWrite = characteristic;
}
});
}
});
}
disconnectFromDevice() {
//if (beltDevice == null) return;
//stopScan();
beltDevice.disconnect();
_bleStatusFromBeltController.add("Disconnect");
print("Disconnect");
// DISCONNECTED
}
}
我的bleBeltNotifyParser_bloc 我无法渲染
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
import 'dart:math' as Math;
import 'package:flutterappbelt3/blocs/ble_service.dart';
class BleBeltNotifyParserBloc{
// final BleService _bloc = BleService();
StreamController<String> _parserInputController = BehaviorSubject<String>.seeded("Parser Input");
Stream<String> get parserInput => _parserInputController.stream;
Sink<String> get parserInputSink => _parserInputController.sink;
BleBeltNotifyParserBloc(){
_parserInputController.stream.listen(_aTest2);
//_bloc.bleNotifyFromBelt.listen((String data) {parserInputSink.add(data); print('Got eem! Input Parser $data');}); Tried various things - such as listening to streams originating from ble_service.
}
void _aTest2(data) {
print("WHAT!!! $data");
}
void aTest() {
//_bloc.bleNotifyFromBelt.listen((String data) {_parserInputController.sink.add(data);});
}
void addToParserController1() {
_parserInputController.sink.add("One");
}
void addToParserController2() {
_parserInputController.sink.add("Two");
}
dispose() {
_parserInputController.close();
}
}
我不想让这个问题无人回答,所以我想指出这个问题的答案在我发布的另一个问题的答案中。
来自已回答问题的评论涉及此问题。
I read it but I don't fully understand the problem (you made a lot of changes to test the stream that I don't know what was the real issue without the tests) but I saw you did the same thing by creating a BleBeltNotifyParserBloc called _bloc inside BleService, and I believe that was the reason it didn't update the UI (for the same reason it didn't work here).
在这个例子中,我正在尝试使用流的继承 Widget/Bloc 架构,然后将另一个问题移至 Provider/Bloc/Async 模型,以尝试弄清楚为什么 UI 在以下时间未更新将数据从 BleService 集团发送到 NotifyParser 集团。
我要感谢 https://whosebug.com/users/3547212/edwynzn 对链接问题的回答!!