繁体   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