I am using flutter_blue_plus for getting bluetooth is on or off. I am getting results in log successfully. But in isOn function, I can't update automatically. What can I do? Do I have to use StreamBuilder in UI?
class BluetoothService with Logger {
BluetoothService() {
log.fine('listening to bluetooth status changes');
FlutterBluePlus.instance.state.listen((result) {
log.fine('bluetooth state changed to ${result.name}');
_lastResult = result;
});
}
BluetoothState _lastResult = BluetoothState.unknown;
/// The last [BluetoothState] that is updated automatically whenever the
/// state changes.
bool get isOn => _lastResult == BluetoothState.on;
Future<void> initialize() async {
try {
await FlutterBluePlus.instance.isAvailable;
} catch (e, st) {
log.warning('unable to initialize bluetooth', e, st);
}
}
}
class BluetoothDeviceList extends StatelessWidget {
const BluetoothDeviceList({Key? key}) : super(key: key);
static const route = 'bluetoothdevicelist';
@override
Widget build(BuildContext context) {
return app<BluetoothService>().isOn
? Scaffold(
body: Center(child: Text('DEVICES')),
)
: Scaffold(
body: Center(child: Text('Bluetooth Close')),
);
}
}
CodePudding user response:
This is definitely a situation where you need to use some state management approach. In our team we use flutter_bloc, in which case your solution would look something like this.
class BluetoothCubit extends Cubit<BluetoothState> with Logger {
BluetoothCubit() : super(BluetoothState.unknown) {
log.fine('listening to bluetooth status changes');
FlutterBluePlus.instance.state.listen((result) {
log.fine('bluetooth state changed to ${result.name}');
emit(result);
});
}
Future<void> initialize() async {
try {
await FlutterBluePlus.instance.isAvailable;
} catch (e, st) {
log.warning('unable to initialize bluetooth', e, st);
}
}
}
class BluetoothDeviceList extends StatelessWidget {
static const route = 'bluetoothdevicelist';
const BluetoothDeviceList({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => BlocProvider(
create: (_) => BluetoothCubit()..initialize(),
child: BlocBuilder<BluetoothCubit, BluetoothState>(
builder: (context, state) => Scaffold(
body: Center(
child: Text(
state == BluetoothState.on ? 'DEVICES' : 'Bluetooth Close',
),
),
),
),
);
}
One of the key changes is that in your stream listener you call emit(result)
. This informs the BlocBuilder
that a new state needs to be displayed.
There are other ways to handle this, but this is the standard approach in our company.