Каков оптимальный подход при реализации уведомлений в нативных приложениях?

Цель данного вопроса - получить подсказку в отношении алгоритма. Реализация генерации событий, думаю, будет более-менее одинаковой вне зависимости от языка, а вот отображение уведомлений будет зависеть от платформы. В этом вопросе мы в такие дебри лезть не будем, но всё-таки чтобы был какой-то пример, рассмотрим обычный таск-менеджер наподобие "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. Создать повторяющийся таймер периодом в 1 минуту
  2. Каждую минуту выгребать все таски из источника данных (такого как база данных) с фильтрацией по времени. Если более детально, то нужно найти те таски, которые имеют элемент массива Notifications, соответствующие текущей минуте. (Как реализовать хранение массивов в БД - отдельный разговор).
  3. Вызвать обработчик события для каждого напоминания

Полагаю, шерстить всю базу данных каждую минуту - плохая идея с точки зрения производительности, а поле Notifications - это не то, что можно сделать индексом для более быстрого поиска. Думаю что языки программирования, используемые для нативной разработки, должны предлагать какой-либо API для подобных задач. Тут ведь ещё важно, чтобы приложение могло отображать оповещения, работая в фоновом режиме.

Хотя этот вопрос об алгоритме, а не о реализации на конкретном языке и программирования и конкретных библиотеках, если Вас интересует мой технологический стэк, то это C#, .NET MAUI и Blazor. Поскольку разработка осуществляется для нескольких платформ одновременно (Android, iOS, macOS, Windows, Tizen), то какой-нибудь библиотеки на Andorid с готовым решением данной задачи будет недостаточно; возможно придётся реализовывать всё самому.


Ответы (1 шт):

Автор решения: Roman-Stop RU aggression in UA

Нужна одна функция getNextNofitication. Запускать ее нужно не раз в минуту, а только когда:

  1. нотификация создается/удаляется/редактируется
  2. нотификация срабатывает.

Каждый раз, когда что-то одно из этого случается, устанавливаем таймер (платформозависимыми средствами) и ждем срабатывания. При срабатывании таймера показываем уведомление и заново вызываем getNextNotification чтоб установить таймер на следующее срабатывание.

Реализовать getNextNotification несложно. Если связь между Task и Nofication храним в отдельной таблице, то просто находим самую первую запись по времени (индекс в этом случае отлично работает).

Если же времена срабатываний храним денормализовано в Task.Notifications, то добавляем в Task еще одно поле NextNotificationTime, которое при сохранении Task устанавливаем в min(Notifications). И опять же поиск в getNextNotification это поиск Task с наименьшим NextNotificationTime (тут тоже индекс будет хорошо работать).

→ Ссылка