簡體   English   中英

如何使用 StateNotifierProvider 在 fcm 處理程序中更新 state?

[英]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

編輯:在哪里傳遞 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM