You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

关键修改说明:

  1. 引入本地存储:添加shared_preferences包的导入,实现设备本地的键值对存储
  2. 初始化时加载历史数据:在initState中异步获取存储实例,读取之前保存的时间值并更新UI
  3. 保存新选择的时间:在确认时间后,把时、分、秒分别存入本地存储,确保重启后能读取
  4. 优化代码结构:拆分通知初始化逻辑,简化日期传递代码,提升可读性

这样修改后,下次重启应用时,页面会自动加载上次选中的通知时间,完美解决你的需求!

内容的提问来源于stack exchange,提问作者shivam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:35:10