[英]How to handle complex state with Riverpods StateNotifierProvider
[英]How to update state in a fcm handler with StateNotifierProvider?
在我的 Flutter 應用程序中,我需要能夠對傳入的 fcm 消息做出反應,這些消息可以通過在其數據有效負載中具有相應的鍵/值對來指示應用程序到 go 不同的導航選項卡。 當前,選定的索引存儲在有狀態小部件中,該小部件還托管底部導航欄:
@override
Widget build(BuildContext context) {
presentTicketsModel = ref.watch(presentTicketsModelProvider);
contractsModel = ref.watch(contractsModelProvider);
return Scaffold(
body: PersistentTabs(
currentTabIndex: index,
screenWidgets: buildPages(),
),
bottomNavigationBar: NavigationBar(
height: 60,
selectedIndex: index,
onDestinationSelected: (index) => setState(() {
this.index = index;
}),
destinations: _buildNavigationDestinations(),
),
);
}
面對新的挑戰,我考慮將 state 索引移動到單獨的 object 中,並使用 Riverpod 的 StateNotifierProvider 提供 state object,如官方文檔 ( https://riverpod.deviders/docs ) 中所述。
我不明白的是:以下服務 class(偵聽傳入的 fcm 消息)如何獲取 state object 並更新索引,以便觀察視圖 class 得到通知並可以切換到目標導航選項卡?
class PushNotificationService {
final fcm = FirebaseMessaging.instance;
Future initialise() async {
print('initialising push notification service...');
}
/// foreground handler
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('onMessage: $message');
// here the state change would be done
});
/// handler if the app has been opened from a background state
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('onMessageOpenedApp: $message');
});
}
}
或者以不同的方式詢問:該服務 class 如何通過 ProviderReference 以訪問提到的 state object 並更改索引值?
該服務目前在 GetIt 注冊為一個懶惰的 singleton:
GetIt locator = GetIt.instance;
void setupLocator() {
locator.registerLazySingleton(PushNotificationService.new);
}
initialise
方法可以有一個Ref
參數,如下所示:
class PushNotificationService {
final fcm = FirebaseMessaging.instance;
Future initialise(WidgetRef ref) async {
print('initialising push notification service...');
}
/// foreground handler
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
// Use ref.read here -> ref.read();
});
/// handler if the app has been opened from a background state
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('onMessageOpenedApp: $message');
});
}
}
然后你可以在調用初始化時傳遞一個ref。
PushNotificationService.initialise(ref);
如果您要在小部件中調用
initialise
,請使用WidgetRef
而不是Ref
WidgetRef
)MyApp
成為ConsumerStatefulWidget
PushNotificationService.initialise(ref);
在initState
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerStatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
ConsumerState<ConsumerStatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends ConsumerState<MyApp> {
@override
initState(){
PushNotificationService.initialise(ref);
super.initState();
}
class _MyAppState extends ConsumerState<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "App",
home: Home(),
);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.