Каков оптимальный подход при реализации уведомлений в нативных приложениях?
Цель данного вопроса - получить подсказку в отношении алгоритма. Реализация генерации событий, думаю, будет более-менее одинаковой вне зависимости от языка, а вот отображение уведомлений будет зависеть от платформы. В этом вопросе мы в такие дебри лезть не будем, но всё-таки чтобы был какой-то пример, рассмотрим обычный таск-менеджер наподобие "Microsoft To Do".
Основная сущность, с которыми работают подобные приложения - задачи (таски).
Подготовил простой C#-класс Task
:
public class Task
{
public required string ID { get; init; }
public required string Title { get; set; }
public string? Description { get; set; }
public bool IsComplete { get; set; } = false;
}
Не вижу смысла создавать отдельную сущность Notification
, потому что любое Notification
имеет смысл только по отношению к конкретному таску, а никаких полей, кроме времени, у этой сущности не будет. Хотя в "Microsoft To Do" List можно устанавливать только одно оповещение на таск, в событиях Google Calendar можно указывать несколько, потому я сделаю также:
public class Task
{
public required string ID { get; init; }
public required string Title { get; set; }
public string? Description { get; set; }
public bool IsComplete { get; set; } = false;
// Новое
public List<DateTime> Notifications { get; set; } = [];
}
Теперь необходимо составить алгоритм генерации событий, согласно которому в нужное время будет известно, о каком таске надо немедленно напомнить пользователю.
Наиболее простое (но вместе с тем и тупое) решение следующее:
- Создать повторяющийся таймер периодом в 1 минуту
- Каждую минуту выгребать все таски из источника данных (такого как база данных) с фильтрацией по времени. Если более детально, то нужно найти те таски, которые имеют элемент массива
Notifications
, соответствующие текущей минуте. (Как реализовать хранение массивов в БД - отдельный разговор). - Вызвать обработчик события для каждого напоминания
Полагаю, шерстить всю базу данных каждую минуту - плохая идея с точки зрения производительности, а поле Notifications
- это не то, что можно сделать индексом для более быстрого поиска. Думаю что языки программирования, используемые для нативной разработки, должны предлагать какой-либо API для подобных задач. Тут ведь ещё важно, чтобы приложение могло отображать оповещения, работая в фоновом режиме.
Хотя этот вопрос об алгоритме, а не о реализации на конкретном языке и программирования и конкретных библиотеках, если Вас интересует мой технологический стэк, то это C#, .NET MAUI и Blazor. Поскольку разработка осуществляется для нескольких платформ одновременно (Android, iOS, macOS, Windows, Tizen), то какой-нибудь библиотеки на Andorid с готовым решением данной задачи будет недостаточно; возможно придётся реализовывать всё самому.
Ответы (1 шт):
Нужна одна функция getNextNofitication
. Запускать ее нужно не раз в минуту, а только когда:
- нотификация создается/удаляется/редактируется
- нотификация срабатывает.
Каждый раз, когда что-то одно из этого случается, устанавливаем таймер (платформозависимыми средствами) и ждем срабатывания. При срабатывании таймера показываем уведомление и заново вызываем getNextNotification
чтоб установить таймер на следующее срабатывание.
Реализовать getNextNotification
несложно. Если связь между Task
и Nofication
храним в отдельной таблице, то просто находим самую первую запись по времени (индекс в этом случае отлично работает).
Если же времена срабатываний храним денормализовано в Task.Notifications
, то добавляем в Task
еще одно поле NextNotificationTime
, которое при
сохранении Task
устанавливаем в min(Notifications)
. И опять же поиск в getNextNotification
это поиск Task
с наименьшим NextNotificationTime
(тут тоже индекс будет хорошо работать).