harunB10
harunB10

Reputation: 5207

Update state each time after notification is received

I have an app which uses local notifications that contain some data. In this case it's some quotes read from a JSON file.

What I'm trying to do is to read another quote every minute and update it in main screen.

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

And this is the place where provider is defined:

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

However this calls the function every second and causes app to crash. I know it is because I call quote.showScheduledNotification(); and notifyListeners() will cause that it goes inside endless loop.

But how to prevent this? How to load it only once and then update lastMessage each time when notification arrives.

For the sake of simplicity I am showing the same quote every time (42).

Upvotes: 0

Views: 925

Answers (1)

Marius Popescu
Marius Popescu

Reputation: 483

Seems like you are looking for an init functionality. If you transform MyApp into a stateful widget, you will be able to use the init method of the stateful widget. This should solve one part of the problem. You should almost never have init functionality inside a build function, since it will be called quite often.


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

PS: For more tips on how to improve the performance of your app, I wrote an article on my blog.

Upvotes: 1

Related Questions