Scheduling multiple notifications has quite an overhead on Android, and can take several seconds on older phones.
This doesn't seem to be an issue on iOS devices, possible due to lack of bridge overhead and optimized data (de-)serialization.
We have business-logic that requires us to calculate custom intervals for scheduling notifications (e.g. monthly interval, birth-control cycle). Because of this, we need to use the schedule function to schedule each notification individually.
We often call the schedule function with 60 notifications (we've set this as a max since iOS has a limit of 64), resulting in a noticeable lag on newer phones, and occasional ANRs on older phones.
Create the option to bulk/batch schedule notifications.
I'll create a pull request with proposed changes to allow for bulk/batch scheduling.
I remember that issue being raised. I see what you describe being a more specialised case that developers should implement on their own should they need it. Using platform channels is more expensive in general that apps that are concerned about the performance to extent would likely need to look at batch operations for all plugins. This leads to an awkward API IMO and I wasn't thinking this plugin is going to help solve every use case. As such I'm not looking at a PR.
I think it would be worth looking more if the performance is strictly around schedule or if it applies to show as well. If it's just the former then perhaps changing how the notifications are saved to shared preferences would help. Commenting out the Java code on saving to shared preferences would be a way to check as well to see if it makes a significant difference to the schedule method
Thanks for the quick reply.
I understand your concerns. However, this is a crucial feature for us, so we're going ahead and implementing it in a fork for now. We don't think it makes the API as awkward as one could fear, and I'll make a PR that I hope you will take a look at anyway.
We've looked into the performance, and there are basically two main culprits: communication over the bridge and instantiation of the GsonBuilder here (being called multiple times).
Sorry should clarify what I meant earlier is that not looking at merging one at this stage. But yes do open a PR, be interested to see what you come up with as well. Ignoring the batch scheduling, you raise a good point that perhaps GsonBuilder could just be created once. That could be a improvement done on it's own
I've made a tweak in the latest release (1.1.5) to reuse the Gson instance. In my own testing on the emulator, scheduling 60 notifications has gone from ~900 milliseconds to ~700 milliseconds
@MaikuB looks good! :+1:
We've ran some tests on physical devices, which also showed that the actual scheduling of the notifications on the Android side (through AlarmManager) doesn't take more than ~1ms, even on older devices. As suspected, the communication over the bridge is the main culprit.
With the changes we've made (in addition to the reuse of the Gson instance), we've managed to reduce the time even more. The numbers are averages from 20 iterations of scheduling 60 notifications:
OnePlus 6 running Android 10
From ~1510ms to ~70ms (factor of ~21)
Motorola MotoX 2nd gen. running Android 6
From ~8980ms to ~260ms (factor of ~34)
We've been busy with releases and getting these changes out, but I'll try to find some time the coming days to rebase our fork on the latest master and make a PR that you can have a look at.
Sounds good
@hurrba I use a different aproach i start flutter_local_notification in a different isolate! I use a plugin called isolate_handler to handle the use of a plugin inside an isolation.
@taciomedeiros apologies for the late response but do you think you could spin a minimal sample app or code snippet to demonstrate this? After looking at the PR I'm leaning towards not including it so if you have a code snippet then we could look at including the code snippet directly or including a link that would lead to the code snippet e.g. a reply in this thread
Also running into this. Moving from a native Android and native iOS app to a Flutter app.
The app schedules multiple notifications, and it is noticeably slower using the plugin, which looks to be because of the platform channel communication.
I'll look into the isolate plugin that @taciomedeiros mentioned.
Closing as bulk scheduling isn't a core API (as in it's not something native APIs expose). Part of the optimisation done within the PR #683 was to wait until all notifications were scheduled before it would save the details to shared preferences. Saving to shared preferences is needed on Android to retrieve the data so that notifications remain scheduled after the phone is rebooted). There's an issue with this approach as if scheduling one of the notifications fails (e.g. missing some details), then nothing gets shared preferences.
Therefore, I'd say for those that need this level of optimisation in their app to either to look at isolates that @taciomedeiros mentioned or have your own fork and that applies the changes done in #683
@MaikuB @Sociosoftware
Sorry for late answer. I hope it helps.
https://gist.github.com/taciomedeiros/50472cf94c742befba720853e9d598b6#file-isolate_handler_example-dart
@taciomedeiros no worries, thanks a lot for that :)
Most helpful comment
@MaikuB looks good! :+1:
We've ran some tests on physical devices, which also showed that the actual scheduling of the notifications on the Android side (through
AlarmManager) doesn't take more than ~1ms, even on older devices. As suspected, the communication over the bridge is the main culprit.With the changes we've made (in addition to the reuse of the
Gsoninstance), we've managed to reduce the time even more. The numbers are averages from 20 iterations of scheduling 60 notifications:OnePlus 6 running Android 10
From
~1510msto~70ms(factor of~21)Motorola MotoX 2nd gen. running Android 6
From
~8980msto~260ms(factor of~34)We've been busy with releases and getting these changes out, but I'll try to find some time the coming days to rebase our fork on the latest master and make a PR that you can have a look at.