【问题标题】:Flutter : Strange behavior of Shared PreferencesFlutter:共享首选项的奇怪行为
【发布时间】:2021-03-05 17:59:30
【问题描述】:

我遇到了共享首选项值不一致的问题。我会尽量简单地描述它。

我正在使用 Firebase 云消息传递推送通知。当应用程序处于后台并收到通知时,将调用下面的后台处理程序。

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  final int counter = (prefs.getInt('badge') ?? 0) + 1;

  prefs.setInt('badge', counter).then((bool success) {
    print(counter);
  });
}

我的小部件使用 WidgetsBindingObserver 来确定生命周期状态。当我进入应用程序时,该小部件的状态为 onResume,我想从这样的共享首选项中读取该徽章值。

void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      final SharedPreferences prefs = await SharedPreferences.getInstance();
      final int counter = (prefs.getInt('badge') ?? 0); 
      print(counter);
    }
  }

场景 1:

  • 应用打开,收到通知 - 将徽章字段设置为 1。
  • 应用在后台,收到通知 - 后台处理程序将徽章字段设置为 2。
  • 应用程序已恢复,读取徽章字段,它仍然是 1。

场景 2:

  • 应用打开,收到通知 - 将徽章字段设置为 1。
  • 应用在后台,收到通知 - 后台处理程序将徽章字段设置为 2。
  • 应用在后台,收到通知 - 后台处理程序将徽章字段设置为 3。
  • 应用程序已恢复,读取徽章字段,它仍然是 1。

问题:知道为什么字段没有更新吗?

【问题讨论】:

  • 你找到这个问题的答案了吗?

标签: flutter firebase-cloud-messaging sharedpreferences


【解决方案1】:

SharedPreferences 或任何其他本地存储在 _firebaseMessagingBackgroundHandler 中不起作用。

您应该在 getInitialMessage 或 onMessageOpenedApp 上捕获它。 https://firebase.flutter.dev/docs/messaging/notifications/

TL;DR: 当应用程序从终止状态打开时触发 getInitialMessage。当应用程序从后台状态打开时会触发 onMessageOpenedApp。

FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage message) {
  if (message != null) {
    Navigator.of(context).pushNamed('/messages', arguments: message.data);
  }
});

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
  if (message != null) {
    Navigator.of(context).pushNamed('/messages', arguments: message.data);
  }
});

【讨论】:

    【解决方案2】:

    SharedPreferences 可用于后台事件处理程序。问题是后台处理程序在不同的隔离中运行,因此,当您尝试获取数据时,共享首选项实例为空。为避免这种情况,您只需强制刷新:

    SharedPreferences prefs= await SharedPreferences.getInstance();
    await prefs.reload();
    final int counter = (prefs.getInt('badge') ?? 0);
    

    在相同的模式下,如果可以在后台 hadler 中修改共享首选项,请确保在尝试读取它们的主隔离时调用此“重新加载”函数。

    【讨论】:

    • reload 方法会清除共享首选项中的数据
    • 能否请您进一步说明这一点
    • 谢谢你!对于任何想知道的人,这里是 .reload() 的文档: 从主机平台获取最新值。使用此方法可以在应用程序运行时观察在本机代码中所做的修改(不使用插件)。
    猜你喜欢
    • 2019-10-01
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 2020-08-01
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多