【问题标题】:Flutter - SharedPreferences saving listFlutter - SharedPreferences 保存列表
【发布时间】:2021-04-14 15:50:27
【问题描述】:

我有一个连接到 Firebase 的应用程序,我正在制作一个屏幕来显示所有发送的通知,因为我正在使用 SharedPreferences。但是当通知到达地图时,我将其放在列表 > 中,以显示通知。

      String title, body;
      Map<dynamic, dynamic> notific;
      List<Map<dynamic, dynamic>> notifList = [];
///Widget
    return Scaffold(
          extendBody: true,
          backgroundColor: widget._colors.white,
          appBar: appBar,
          body: ListView.builder(
            itemCount: notifList.length,
            itemBuilder: (context, i) {
              return Card(
                margin: EdgeInsets.all(10),
                elevation: 4,
                child: ListTile(
                  title: Text(
                    notifList.elementAt(i)['title'],
                  ),
                  subtitle: Text(
                    notifList.elementAt(i)['body'],
                  ),
                ),
              );
            },
          ),
        );
      }

Firebase 方法

  Future<dynamic> fcmMessageReceiver() async {
    FirebaseMessaging.instance.getInitialMessage().then((value) {
      if (value != null) {}
    });

    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      if (message.notification != null) {
        notific = {
          'title': message.notification.title,
          'body': message.notification.body
        };
        notifList.add(notific);
        setState(() {
          title = message.notification.title;
          body = message.notification.body;
        });
        print('MENSAGEM: $notific');
      }
    });
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {});
  }

Shared Preferences 方法,在 initState() 上调用

  void savePush() async {
    SharedPreferences sharePref = await SharedPreferences.getInstance();
    final strList = sharePref.getStringList('push')??[];
    sharePref.setStringList('push', notifList.toString());
  }

我的问题是,我怎样才能保留这些通知,以便每当我想看到它们时,我都可以轻松获取它们,并使用通知设置卡片?

【问题讨论】:

  • 那么,基本上你想要的是将 List> 保存在 SharedPreferences 中,对吧?
  • 是的,但我不知道该怎么做。我需要保存列表,以便稍后在 Scaffold 上显示通知。

标签: firebase flutter dart


【解决方案1】:

所以,有很多方法可以解决这个问题,我的一些方法是将每条消息转换为JSON encoded string,然后将其推送到sharedPreference.setStringList(list)。另一种方法是将整个列表设为JSON encoded string,并通过调用sharedPreference.setString(list) 将其像字符串一样保存到SharedPreferences


假设你的消息列表是这样的:

List<Map<String, dynamic>> messagesForUI = [];

而且,您已经像这样初始化了 SharedPreferences 和来自 SharedPreferences 的先前消息:

SharedPreferences sharedPreference = await SharedPreferences.getInstance();
List<String> sharedPreferenceMessages = [];

现在,要从 SharedPreferences 检索您之前的所有消息,然后在 initState 方法中将之前的消息设置为 messagesForUI,您可以这样做:

sharedPreferenceMessages = sharedPreference.getStringList("messages") ?? [];
sharedPreferenceMessages.forEach((element) {
  Map<String, dynamic> messageMap = Map<String, dynamic>.from(json.decode(element));
  messagesForUI.add(messageMap);
});

现在,您的清单已准备就绪。

假设您有一条来自 FCM 的新消息,并且您想将其保存到 SharedPreferences。让我们以这种方式保存新消息:

Map<String, dynamic> newMessage = Map<String, dynamic>.from(fcmMessage);

setState((){
  messagesForUI.add(newMessage);
});

String newMessageJson = json.encode(newMessage);
sharedPreferenceMessages.add(newMessageJson);
sharedPreference.setStringList("messages", sharedPreferenceMessages);

给你。您也可以通过调用sharedPreference.setString(map) 将消息保存到SharedPreferences,就像这种方法一样。如果需要演示该过程,请在此处发表评论。

示例代码:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class NotificationRoute extends StatefulWidget {
  @override
  _NotificationRouteState createState() => _NotificationRouteState();
}

class _NotificationRouteState extends State<NotificationRoute> {
  List<Map<String, dynamic>> messagesForUI = [];
  List<String> sharedPreferenceMessages = [];
  SharedPreferences sharedPreference;

  @override
  void initState() {
    init();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: messagesForUI.isEmpty
          ? Center(
              child: Text("No notifications"),
            )
          : ListView.builder(
              itemBuilder: (context, index) {
                final Map<String, dynamic> message = messagesForUI[index];
                return ListTile(
                  title: Text(message["title"]),
                  subtitle: Text(message["body"]),
                );
              },
              shrinkWrap: true,
              physics: ScrollPhysics(),
              scrollDirection: Axis.vertical,
              itemCount: messagesForUI.length,
            ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Map<String, dynamic> newMessage = {"title": "test title", "body": "test body"};

          setState(() {
            messagesForUI.add(newMessage);
          });

          String newMessageJson = json.encode(newMessage);
          sharedPreferenceMessages.add(newMessageJson);
          sharedPreference.setStringList("messages", sharedPreferenceMessages);
        },
        child: Icon(Icons.add),
      ),
    );
  }

  init() async {
    sharedPreference = await SharedPreferences.getInstance();
    sharedPreferenceMessages = sharedPreference.getStringList("messages") ?? [];
    sharedPreferenceMessages.forEach((element) {
      Map<String, dynamic> messageMap = Map<String, dynamic>.from(json.decode(element));
      messagesForUI.add(messageMap);
    });
  }
}


现在,由于我的项目没有任何 FCM 设置,我只需通过 FloatingActionButton 将消息添加过程复制到 SharedPreference

编码愉快:D

【讨论】:

  • 显然它不起作用。当您退出并重新进入屏幕时,通知会消失。我应该在 Text () 小部件中继续调用它吗? notifList.elementAt (i) ['title']
  • 你是否在 initState 方法中从 SharedPreferences 初始化了 messagesForUI ?我假设您正在使用 StatefulWidget 小部件
  • 我正在使用 Statefull 是的,但它目前在类而不是方法中,因为我在脚手架小部件中调用 messagesForUI 以显示来自 firebase 的新旧通知。
  • 兄弟,我知道您在脚手架小部件中调用 messagesForUI。但是仔细看,你的 StatefulWidget 小部件有 initState 方法、build 方法和 destory 方法。您在 build 方法中返回脚手架小部件,这是正确的。但是您必须在 initState 方法中设置 messagesForUI 变量。这样,每当你进入屏幕,你的messagesForUI列表就会一直更新。
  • 但是我要如何调用脚手架中的变量呢?我是 Flutter 的新手,我仍然很容易迷失状态方法。
猜你喜欢
  • 2020-11-28
  • 1970-01-01
  • 2019-09-23
  • 1970-01-01
  • 2020-09-13
  • 2019-09-30
  • 2021-04-20
  • 2017-12-06
  • 1970-01-01
相关资源
最近更新 更多