使用后退按钮退出应用程序后,我只能从共享偏好中获取值

Posted

技术标签:

【中文标题】使用后退按钮退出应用程序后,我只能从共享偏好中获取值【英文标题】:I can only get the value from shared preference after exiting the app using back button 【发布时间】:2021-11-29 08:25:02 【问题描述】:

有两种方法可以退出我们的 android (Flutter) 应用,我们可以反复按返回按钮,也可以直接按主页按钮

如果用户按下home button(不是返回按钮),则应用程序将在后台运行。我向用户发送 FCM(Firebase 云消息传递)推送通知,应用程序将在后台处理程序中接收消息。然后我像这样在共享首选项中保存一个字符串

Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async 
  
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString("myKey", "value here");
  
  final testValue = prefs.getString("myKey");
  print("value in background handler: $testValue");  // I confirm I can get the saved value here

从上面的代码可以看出,我可以从firebaseMessagingBackgroundHandler中的共享偏好中获取值

用户收到推送通知后,打开应用,直接打开首页。

在首页,我尝试获取之前保存的值

  @override
  void initState() 
    super.initState();

    WidgetsBinding.instance?.addPostFrameCallback((_) async 

      final prefs = await SharedPreferences.getInstance();
      final savedValue = prefs.getString("myKey");
      print(savedValue); // I get null here initially

    );
  

如您所见,当我直接返回应用程序时,我得到了 null 值。我必须再次使用back button 退出应用程序,然后最终我可以从共享首选项中获取字符串值。

为什么我必须按返回按钮才能从共享偏好中获取值?如何解决?

【问题讨论】:

仅仅因为您让print("value in background handler: $testValue"); 打印该值并不意味着它已保存在本地存储中。开发人员最有可能将数据保存在 RAM 中的某个集合中,这样您就不必在应用程序的生命周期内从磁盘加载它。基本上,这意味着无论出于何种原因(可能是操作系统的某些限制),都不会执行 IO 操作,并且如果您阅读有关共享首选项的文档,则会有关于可靠性的说明。 @Alexa289 你找到解决方案了吗? 【参考方案1】:

initState 在第一次构建小部件之前执行一次。如果您将应用置于后台,然后再次打开,initState 将不会再次运行。

(不是您的问题的一部分,但即使您想在第一次构建之前从 Shared Preferences 中读取某些内容,initState 也不是一个真正适合它的地方,因为它不能是异步的,这就是为什么您使用addPostFrameCallback。我宁愿建议在你的构建方法中使用FutureBuilder,这样你就可以等待异步操作的结果,如果你需要它的结果来构建。)

因此,您的值可能已保存到共享首选项中,但您需要找到另一种方式来读取它。如果你想检测你的应用何时从后台恢复,你可以通过观察应用生命周期变化来实现,例如in this article。

但我认为有一种更简单的方法,如果您想在您的应用处于后台期间用户点击通知时获取通知数据。您可以收听onMessageOpenedApp,然后您可以直接在代码中获取消息,无需共享首选项:

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) 
  
);

【讨论】:

是的,initState 只会被调用一次,但是addPostFrameCallback 里面的代码可以执行多次,我的主页位于底部导航栏中的索引 0,所以如果我从tab 0 到 tab 1 再到 tab 0,addPostFrameCallback 将再次执行 不幸的是,如果将其更改为 onResume 回调,它将是相同的 :( 非常感谢彼得。但我也无法在onMessageOpenedApp 上实现它,因为我正在尝试使用 FCM 进行“静默更新”,没有推送通知显示。 好吧,我误会了,你写的是“收到推送通知后,用户会打开应用”,我以为是点击通知的意思。

以上是关于使用后退按钮退出应用程序后,我只能从共享偏好中获取值的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Cordova 中的 android 设备后退按钮退出应用程序?

在颤动中按下移动后退按钮后网站应用程序未退出

注销后的 CodeIgniter 后退按钮

颤振:如何在按下后退按钮时不退出应用程序

颤振:我怎样才能抓住后退按钮按下退出我的应用程序

Android应用程序中的后退按钮无法退出应用程序