Notification Bar Overview

Сложность 100-200

В данном посте я хочу дать очень краткую обзорную информацию по компоненту Notificaion Bar, который позволяет отображать внутрипрограммные уведомления. Я не буду заострять внимание на реализации, всех тонкостях работы с этим компонентом. Просто расскажу как пришла идея и основные возможности, а так же некоторые планы на будущее.

Идея создания

Все идеи как всегда идут из жизни, из каких-то конкретных потребностей и фантазий на тему того как можно было бы их реализовать. В данном случае идея пришла из приложения, которое мы разрабатывали в рабочее время. Приложение являлось толстым клиентом для расчета/перевода внутренней бухгалтерии во внешнюю, и многие операции совершались достаточно долго. Долго это значит от 2 минут до 30 и более. Конечно же на это время приложение не зависало, было вполне отзывчивым, но отзывчивым фактически только для одного действия, отмены долгоработающего метода. Всякие визуальные игры в виде сортировки по колонком не берем за серьезный функционал.

Архитектура приложения была построена так, что с долгой операцией (расчетами) связанной с базой данных был связан Id, который переписывался для каждого такого действия с базой, получается что в один момент можно было делать только одно большое действие и не переходить с экрана, для того, чтобы в конце концов узнать результат работы.

Очень хотелось сделать так, чтобы можно было достаточно безболезненно модифицировать имеющийся код, чтобы можно было осуществлять свободную навигацию по приложению и видеть отчет о завершенном действии в области уведомлений приложения. Отчего-то хотелось именно в самом приложении обо всем сообщать, а не выносить в «иконку рядом с часами». Не буду лукавить, это «отчего-то» пришло от частого созерцания области уведомлений на планшете с Android 4, и мне очень нравится то, как сделаны уведомления в системе и хотелось их как-то повторить.

Получается, что есть два желания, которые коррелируют друг с другом очень хорошо, по крайней мере лучше, чем идеи в фильме Super 8. А так как идеи достаточно давно вынашивались и могла появится конкретная польза, то я решил реализовать всё не отдавая себя прокрастинации.

Итак, основная идея:

Необходимо иметь возможность так проинстументализировать модели, чтобы они могли сообщить об окончании работ пользователю. Так же должна быть возможность перейти на экран, который сгенерировал сообщение.

Все остальные вещи могут рассматриваться как дополнительные украшательства. Но по возможности стоит реализовать, если стоимость будет низка.

 

Использование в программе

Общий вид сообщений представлен на скриншоте ниже:

Процесс работы сообщений на видео можно посмотреть в блоге. Или здесь

На скриншоте выше показано три уведомления, подробная информация по двум из них, время прихода сообщений.

Общим сценарием можно назвать следующую последовательность действий:

  • на целевом экране запускается долгоиграющая функция
  • пользователь переходит на любой другой экран
  • по окончании функции на целевом экране появляется уведомление
  • по нажатию на уведомление пользователь переходит на целевой экран
  • уведомление исчезает

Естественно нужно учитывать еще некоторые параметры при показе уведомлений:

  • Если момент окончания события наступает, когда пользователь на целевом экране, то никаких уведомлений дополнительных показывать не стоит.
  • Подробные сообщения показываются при наведении на уведомление. При этом не должно быть моментальных срабатываний, когда пользователь проводит мышью по уведомлению случайно.
  • Подробные сообщения показываются до тех пор, пока пользователь наводит мышью на уведомление либо само сообщение.
  • Следует ограничивать количество подробных сообщений показываемых за раз
  • Так же следует ограничивать количество уведомлений в строке. Те, которые не поместились, следует сохранять и возвращать в область видимости, если количество показываемых уведомлений сократилось.
  • Немаловажным моментом так же должна быть возможность удалить уведомление пользователем.

 

Из функциональных частей нужно отметить следующие моменты:

  • Настройка иконки уведомления
  • Настройка заголовка сообщения
  • Настройка текста сообщения
  • Однозначное сопоставление методов начала и конца логического действия, если модель генерирует больше одного пользовательского сообщения.

Кроме всего этого в Notification Bar я включил систему сообщений, которые могут самостоятельно отслеживать время своего отображения. Подробнее об этом можно почитать в моей прошлой статье.

Технические моменты

С технической точки зрения у проекта много зависимостей от сторонних библиотек, но честно сказать, все эти библиотеки так и так используются во всех моих проектах, все они бесплатны.

  • PostSharp Community Edition
  • PostSharp Threading Toolkit
  • PostSharp Domain Toolkit
  • Rx Framework
  • StructureMap
  • MakeMeAsync

Естественно все эти зависимости вам не надо устанавливать вручную. Все они будут установлены при загрузке NuGet пакета.

Для включения компонента в свою программу необходимо будет сделать две вещи:

  • Реализовать интерфейс INotificationViewManager
  • Инструментализировать желаемые модели

Кратко расскажу про эти пункты

Интерфейс

Интерфейс представляет собой следующее:

Первый метод необходим для того, чтобы компонент мог переводить пользователя на нужный экран. Второе свойство необходимо для определения, нужно ли отображать уведомление пользователю.

Не думаю, что в этом должны возникнуть сложности в реальном приложении, т.к. так или иначе в любом достаточно большом приложении без менеджера отображений не обойтись.

Инструментализация

Если реализация интерфейса и может принести некоторые сложности, то инструментализация должна быть точно быть максимально простой и понятной, так как использоваться будет почаще.

Основные атрибуты для работы:

SupportNotificationBar – используется чтобы указать, что модель должна отслеживаться системой уведомлений. Применяется только на класс. Никаких дополнительных параметров и настроек не имеет. Работает как простой маркер. Обязательным условием является реализация интерфейса IDisposable.

TriggerNotifyAction – используется чтобы указать на метод начала асинхронной операции, конец которой надо будет отслеживать. В качестве опционального строкового параметра принимает Id, по нему будет происходить совмещение методов начала и конца логической операции. Если в модели только одна операция для отслеживания, то указывать не обязательно. Используется только для методов.

NotifyActionEnds ­– используется чтобы указать об окончании логической операции. Id операции так же является опциональным параметром. Кроме этого возможно указать иконку для уведомления с помощью параметра Icon. Заголовок для сообщения – Title, и тело сообщения Message. Используется только для методов. Возможны разные способы задания сообщений. Подробности позже.

NotifyContextImportant — этим атрибутом помечаются свойства класса, которые были изменены в методе помеченным атрибутом NotifyActionEnds и должны быть восстановлены при переходе на экран.

 

Более подробно об этих атрибутах и прочих возможностях в следующих постах.

Пути развития

В планах сделать дополнительный атрибут для отображения информации с отображением прогресса. Т.е. в самой иконке или же еще как-то будет отображаться процент выполнения задачи. Естественно, что этот процент будет считать не компонент, а он будет отображаться на основе некоторых данных со специальным интерфейсом.

После того, как реализую отображение прогресса операции, можно будет подумать о том, возможно ли сделать отображения сообщений произвольного типа, т.е. свободно перерисовывать подробное сообщение и отображать там дополнительные средства управления. Насколько это будет удобно в реализации, много ли придется менять в концепции всего компонента.

Так же надо будет что-то придумывать с темами оформления, так как на данный момент это никак не может быть заменено вне исходного кода компонента.

Установка

Установить компонент можно с помощью, уже ставшего родным, NuGet менеджера. Для этого необходимо набрать команду

При установке будут подгружены так же все зависимые компоненты и пакеты.

 

 

В следующих постах я расскажу подробнее о том, как настраивается компонент внутри приложения, особенности реализации. Где и что можно подкрутить для себя в исходном коде. Принципы построения компонента.

Надеюсь вы интересно провели время!

 

 

Hard’n’Heavy!

 

 

Оставить комментарий