Flutter本地通知:如何持久化存储选中的时间值?
解决Flutter通知时间持久化问题
我来帮你搞定这个通知时间持久化的问题!你遇到的核心问题是setState()只能在应用运行期间维护内存中的变量状态,一旦应用重启,这些内存里的数值就会被清空,所以我们需要把选中的时间存储到设备本地。这里推荐使用shared_preferences这个轻量且易用的本地存储插件,它能帮我们快速实现键值对的持久化。
步骤1:添加依赖
首先在你的pubspec.yaml文件中添加shared_preferences依赖:
dependencies: flutter: sdk: flutter flutter_local_notifications: ^16.1.0 # 确保使用适配的版本 flutter_datetime_picker: ^1.5.1 fluttertoast: ^8.2.4 shared_preferences: ^2.2.2 # 新增本地存储依赖
执行flutter pub get完成依赖安装。
步骤2:修改SettingPage代码
下面是修改后的完整代码,我标注了关键修改点:
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:shared_preferences/shared_preferences.dart'; // 导入本地存储包 import 'package:font_awesome_flutter/font_awesome_flutter.dart'; // 若用FontAwesome需保留此导入 class SettingPage extends StatefulWidget { @override _SettingPage createState() => _SettingPage(); } class _SettingPage extends State<SettingPage> { FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin; String notifyTime = "your time"; String nhour = ""; String nminutes = ""; String nseconds = ""; SharedPreferences _prefs; // 声明本地存储实例 @override void initState() { super.initState(); _initLocalStorageAndLoadTime(); // 初始化存储并读取历史时间 _initNotificationPlugin(); // 拆分通知初始化逻辑,代码更清晰 } // 初始化通知插件 void _initNotificationPlugin() { var initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); var initializationSettingsIOS = IOSInitializationSettings(); var initializationSettings = InitializationSettings( android: initializationSettingsAndroid, iOS: initializationSettingsIOS, ); flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); flutterLocalNotificationsPlugin.initialize(initializationSettings); } // 初始化本地存储并加载保存的时间 Future<void> _initLocalStorageAndLoadTime() async { _prefs = await SharedPreferences.getInstance(); // 读取历史存储的时间值,无数据则留空 nhour = _prefs.getString('notify_hour') ?? ""; nminutes = _prefs.getString('notify_minute') ?? ""; nseconds = _prefs.getString('notify_second') ?? ""; // 若有历史数据,更新UI显示 if (nhour.isNotEmpty && nminutes.isNotEmpty && nseconds.isNotEmpty) { setState(() { notifyTime = "$nhour : $nminutes : $nseconds"; }); } } Future _showNotificationWithDefaultSound() async { var androidPlatformChannelSpecifics = AndroidNotificationDetails( 'your channel id', 'your channel name', 'your channel description', importance: Importance.max, priority: Priority.high); var iOSPlatformChannelSpecifics = IOSNotificationDetails(); var platformChannelSpecifics = NotificationDetails( android: androidPlatformChannelSpecifics, iOS: iOSPlatformChannelSpecifics); await flutterLocalNotificationsPlugin.show( 0, 'Learn Local Notification', 'A Local Notification On Button Click', platformChannelSpecifics, payload: 'Default_Sound', ); } Future scheuleAtParticularTime(DateTime timee) async { var time = Time(timee.hour, timee.minute, timee.second); print(time.toString()); var androidPlatformChannelSpecifics = AndroidNotificationDetails( 'repeatDailyAtTime channel id', 'repeatDailyAtTime channel name', 'repeatDailyAtTime description'); var iOSPlatformChannelSpecifics = IOSNotificationDetails(); var platformChannelSpecifics = NotificationDetails( android: androidPlatformChannelSpecifics, iOS: iOSPlatformChannelSpecifics); await flutterLocalNotificationsPlugin.showDailyAtTime( 0, 'Hey! Check your today`s horoscope ', 'Login now to see your today`s horoscope !', time, platformChannelSpecifics ); print('scheduled'); Fluttertoast.showToast( msg: "Notification Scheduled for ${time.hour} : ${time.minute} : ${time.second}", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, backgroundColor: Colors.grey, textColor: Colors.white); setState(() { nhour = time.hour.toString(); nminutes = time.minute.toString(); nseconds = time.second.toString(); notifyTime = "$nhour : $nminutes : $nseconds"; }); // 将选中的时间保存到本地存储 await _prefs.setString('notify_hour', nhour); await _prefs.setString('notify_minute', nminutes); await _prefs.setString('notify_second', nseconds); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Theme.of(context).primaryColor, appBar: AppBar( backgroundColor: Theme.of(context).primaryColor, leading: IconButton( icon: Icon(FontAwesomeIcons.arrowLeft), onPressed: () => Navigator.pop(context), ), title: Text('Setting'), ), body: Theme( data: Theme.of(context).copyWith( canvasColor: Theme.of(context).primaryColor, ), child: Center( child: Container( height: MediaQuery.of(context).size.height - 60.0, child: ListView( scrollDirection: Axis.horizontal, children: <Widget>[ Padding( padding: const EdgeInsets.only(top: 60.0), child: RaisedButton( color: Color(0xffffffff), child: Text( 'Notification time - $notifyTime', style: TextStyle(color: Color(0xff6200ee)), ), onPressed: () { DatePicker.showTimePicker( context, showTitleActions: true, onChanged: (date) { print('change $date'); }, onConfirm: (date) { print('confirm $date'); scheuleAtParticularTime(date); // 简化日期传递逻辑 }, currentTime: DateTime.now(), locale: LocaleType.en, ); }, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30.0), ), ), ), ], ), ), ), ), ); } }
关键修改说明:
- 引入本地存储:添加
shared_preferences包的导入,实现设备本地的键值对存储 - 初始化时加载历史数据:在
initState中异步获取存储实例,读取之前保存的时间值并更新UI - 保存新选择的时间:在确认时间后,把时、分、秒分别存入本地存储,确保重启后能读取
- 优化代码结构:拆分通知初始化逻辑,简化日期传递代码,提升可读性
这样修改后,下次重启应用时,页面会自动加载上次选中的通知时间,完美解决你的需求!
内容的提问来源于stack exchange,提问作者shivam
相关产品推荐
相关产品推荐

