每次收到通知后更新状态

时间:2021-07-21 22:35:33

标签: flutter dart flutter-provider

我有一个应用程序,它使用包含一些数据的本地通知。在这种情况下,它是从 JSON 文件中读取的一些引号。

我想做的是每分钟阅读另一篇引文并在主屏幕中更新。

void main() {
  runApp(ChangeNotifierProvider<QuotesRepository>(
    create: (context) => QuotesRepository.instance(),
    child: MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyApp(),
    ),
  ));
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var quote = Provider.of<QuotesRepository>(context);
    quote.showScheduledNotification();

    return Scaffold(
      appBar: new AppBar(
        backgroundColor: Colors.red,
        title: new Text('Flutter notification demo'),
      ),
      body: new Center(
        child: Text(
          quote.lastMessage.toString(),
          style: GoogleFonts.clickerScript(fontSize: 40.0),
        ),
      ),
    );
  }
}

这是定义提供者的地方:

class QuotesRepository with ChangeNotifier {
  String? lastMessage;

  QuotesRepository.instance();

  Future<void> loadJson(int index) async {
    String data = await rootBundle.loadString('assets/quotes.json');
    Map<String, dynamic> userMap = jsonDecode(data);

    this.lastMessage = userMap['quotes'][index]['quote'];
  }

  Future<void> showScheduledNotification() async {
    int randomValue = 42;
    await loadJson(randomValue).then((value) => showNotificationBody());

    notifyListeners();
  }

  Future<void> showNotificationBody() async {
    FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
        FlutterLocalNotificationsPlugin();
    print("Function called");
    const androidPlatformChannelSpecifics = AndroidNotificationDetails(
      'channel id',
      'channel name',
      'channel description',
      icon: 'flutter_devs',
      largeIcon: DrawableResourceAndroidBitmap('flutter_devs'),
    );

    var iOSPlatformChannelSpecifics = IOSNotificationDetails();
    const NotificationDetails platformChannelSpecifics = NotificationDetails(
      android: androidPlatformChannelSpecifics,
    );
    flutterLocalNotificationsPlugin.periodicallyShow(0, '365<3',
        this.lastMessage, RepeatInterval.everyMinute, platformChannelSpecifics,
        payload: this.lastMessage);
  }
}

然而,这会每秒调用该函数并导致应用程序崩溃。 我知道这是因为我调用 quote.showScheduledNotification();notifyListeners() 会导致它进入无限循环。

但是如何防止这种情况发生?如何仅加载一次,然后在每次通知到达时更新 lastMessage

为了简单起见,我每次都显示相同的引用 (42)。

1 个答案:

答案 0 :(得分:1)

似乎您正在寻找 init 功能。如果您将 MyApp 转换为有状态小部件,您将能够使用 stateful 小部件的 init 方法。这应该可以解决一部分问题。您几乎不应该在 build 函数中使用 init 功能,因为它会经常被调用。


class MyApp extends StatefulWidget {
  const MyApp();

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    var quote = Provider.of<QuotesRepository>(context);
    quote.showScheduledNotification();
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: new AppBar(
        backgroundColor: Colors.red,
        title: new Text('Flutter notification demo'),
      ),
      body: new Center(
        child: Text(
          Provider.of<QuotesRepository>(context).lastMessage.toString(),
          style: GoogleFonts.clickerScript(fontSize: 40.0),
        ),
      ),
    );
  }
}