在 Flutter 中,如果你想告知多个地方设备已连接,常见的方式是通过 状态管理 工具进行全局通知。可以使用 Provider
、ChangeNotifier
或者 Stream
来实现这种全局状态的更新,并在多个地方监听连接状态的变化。这里推荐使用 Provider
+ ChangeNotifier
的方式,因为它易于理解和使用。
使用 ChangeNotifier
通知多个地方设备已连接
-
定义
BluetoothConnectionNotifier
:创建一个ChangeNotifier
来管理设备连接状态。 -
全局提供
BluetoothConnectionNotifier
:在顶层通过ChangeNotifierProvider
进行状态管理。 -
监听设备连接状态:在需要的地方使用
Consumer
或Provider.of
监听设备连接状态的变化。
具体步骤
1. 定义 BluetoothConnectionNotifier
这个类负责管理蓝牙设备的连接状态,并通过 notifyListeners()
通知监听者状态的变化。
import 'package:flutter/material.dart';
class BluetoothConnectionNotifier extends ChangeNotifier {
bool _isConnected = false;
bool get isConnected => _isConnected;
void setConnected(bool connected) {
_isConnected = connected;
notifyListeners(); // 通知所有监听者状态发生变化
}
}
2. 在顶层提供 BluetoothConnectionNotifier
你可以在应用的根部,或者在需要监听的页面上,使用 ChangeNotifierProvider
提供 BluetoothConnectionNotifier
。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => BluetoothConnectionNotifier(),
child: MyApp(),
),
);
}
3. 连接设备并通知其他地方
当设备连接成功后,通过 BluetoothConnectionNotifier
来更新连接状态,这样所有监听者都会收到通知。
void onBluetoothConnected(BuildContext context) {
// 当设备连接成功时,通知连接状态变化
final bluetoothNotifier = Provider.of<BluetoothConnectionNotifier>(context, listen: false);
bluetoothNotifier.setConnected(true); // 设置连接状态为已连接
}
4. 在多个地方监听连接状态
通过 Consumer
或 Provider.of
,在需要的地方监听连接状态的变化。可以在多个页面或者组件中监听。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class SomeWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<BluetoothConnectionNotifier>(
builder: (context, bluetoothNotifier, child) {
return Text(
bluetoothNotifier.isConnected ? '设备已连接' : '设备未连接',
style: TextStyle(fontSize: 20),
);
},
);
}
}
5. 其它组件也可以通过 BluetoothConnectionNotifier
获取状态
如果在其他页面或组件中,也可以随时通过 Provider.of
获取连接状态。
bool isDeviceConnected(BuildContext context) {
final bluetoothNotifier = Provider.of<BluetoothConnectionNotifier>(context);
return bluetoothNotifier.isConnected;
}
总结
- 通过
ChangeNotifier
管理设备连接状态。 - 使用
ChangeNotifierProvider
提供全局状态。 - 通过
Consumer
或Provider.of
在多个地方监听状态变化,从而做到多个地方都可以响应设备的连接状态。
这样,当蓝牙设备连接成功后,所有监听连接状态的地方都会自动收到通知并更新 UI。
要在 ViewModel
中监听全局状态(比如蓝牙设备的连接状态),你可以通过 Provider
或者 ChangeNotifier
来监听状态的变化。关键步骤是:在 ViewModel
内部注册监听器,并确保 ViewModel
知道什么时候更新它的状态。
具体步骤:
1. 在 ViewModel
内部监听 BluetoothConnectionNotifier
可以在 ViewModel
中通过 Provider
获取 BluetoothConnectionNotifier
,并在 init
阶段设置一个监听器,监听连接状态的变化。这里假设你的 ViewModel
继承自 ChangeNotifier
,这样它可以在状态变化时通知 UI。
2. 通过 Provider
或 BuildContext
获取 BluetoothConnectionNotifier
为了确保 ViewModel
能够监听到 BluetoothConnectionNotifier
的状态变化,你需要在 ViewModel
初始化时获取 BluetoothConnectionNotifier
,然后在 notifyListeners
时更新 ViewModel
。
代码实现
1. ViewModel
中监听 BluetoothConnectionNotifier
假设我们有一个 BluetoothScanViewModel
,它需要监听蓝牙设备的连接状态,并在状态变化时做出响应。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'bluetooth_connection_notifier.dart'; // 你定义的蓝牙连接状态管理类
class BluetoothScanViewModel extends ChangeNotifier {
bool _isConnected = false;
bool get isConnected => _isConnected;
/// 初始化方法
void init(BuildContext context) {
// 获取 BluetoothConnectionNotifier 实例并监听状态变化
final bluetoothNotifier = Provider.of<BluetoothConnectionNotifier>(context, listen: false);
// 监听蓝牙连接状态的变化
bluetoothNotifier.addListener(() {
_isConnected = bluetoothNotifier.isConnected;
// 状态变化时,通知UI更新
notifyListeners();
});
}
/// 处理其他业务逻辑
void performSomeAction() {
if (_isConnected) {
// 设备已连接,执行一些逻辑
print("设备已连接");
} else {
// 设备未连接,处理未连接逻辑
print("设备未连接");
}
}
}
2. 在 Widget
中初始化 ViewModel
你需要在页面中调用 ViewModel
的 init
方法,确保它能够在构建的时候监听到 BluetoothConnectionNotifier
的状态变化。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'bluetooth_scan_viewmodel.dart';
import 'bluetooth_connection_notifier.dart';
class BluetoothScanPage extends StatefulWidget {
@override
_BluetoothScanPageState createState() => _BluetoothScanPageState();
}
class _BluetoothScanPageState extends State<BluetoothScanPage> {
late BluetoothScanViewModel viewModel;
@override
void initState() {
super.initState();
// 使用 WidgetsBinding 确保在 build 之后调用 viewModel 的 init 方法
WidgetsBinding.instance.addPostFrameCallback((_) {
viewModel.init(context); // 初始化 ViewModel 的监听器
});
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => BluetoothScanViewModel(),
child: Consumer<BluetoothScanViewModel>(
builder: (context, viewModel, child) {
return Scaffold(
appBar: AppBar(
title: Text(viewModel.isConnected ? "设备已连接" : "设备未连接"),
),
body: Center(
child: ElevatedButton(
onPressed: viewModel.performSomeAction, // 执行逻辑
child: Text("执行操作"),
),
),
);
},
),
);
}
}
关键点解释:
监听
BluetoothConnectionNotifier
:在ViewModel
的init
方法中,我们通过Provider.of
获取全局的BluetoothConnectionNotifier
实例,并注册了一个监听器,当isConnected
状态变化时,调用notifyListeners
通知 UI。WidgetsBinding.instance.addPostFrameCallback
:为了确保在initState
中能够访问BuildContext
,我们使用了WidgetsBinding.instance.addPostFrameCallback
来推迟调用ViewModel
的初始化,避免在initState
中直接使用BuildContext
报错。performSomeAction
:ViewModel
的方法可以根据isConnected
的状态进行不同的业务逻辑处理。
总结:
- 在
ViewModel
中通过Provider
获取BluetoothConnectionNotifier
,并设置监听器。 - 当状态变化时,通过
notifyListeners
通知 UI 更新。 - 使用
WidgetsBinding.instance.addPostFrameCallback
确保ViewModel
的init
能够在正确的BuildContext
构建后执行。