Skip to content

A small library a kind of architecture pattern implementation for android app's development and some samples

Notifications You must be signed in to change notification settings

remdevlab/android-rem-wetweex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

android-rem-wetweex

A small library a kind of architecture pattern implementation for android app's development and some samples

Обзор

Идея подхода и, в какой-то, степени, архитектуры, состоит в том, чтобы попытаться решить основные типичные задачи, которые приходиться решать разработчикам, почти на каждом проекте, вне зависимости от того, какими библиотеками (чистое SDK или RxJava) или архитектурными подходами воспользоваться (MVP, MVVM, Clean Architecure). Данный подход своего рода гибрид разных подходов, но наверное скорее похож на MVVM, с некоторыми особенностями

Wetweex

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

Компоненты

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

  1. TweexView – базовый объект, представляющий пользовательский интерфейс. В контектсте Android это будет активность или фрагмент. Аналог View в MVP. При создании, инициирует создание TweexViewModel и Coordinator
  2. TweexViewModel – объект, хранящий все данные, необходимые для отображения на пользовательском интерфесе. Должен быть максимально похож на POJO, если можно так выразиться, т.е. не выполнять никаких действий, только лишь инкапсулировать поля. Зачастую это просто поля TweexLiveData, либо дргуие POJOs. Чем-то похож на *ViewModel *в androidx (Android Arch), но в отличие от него, который переживает лишь пересоздание активности при повороте экрана, TweexViewModel в контексте *Coordinator *живет пока TweexView не будет уничтожена как более ненужная (onDestroy)
  3. Coordinator – компонент, связывающий воедино бизнес слой приложения (т.е. все модели, сервисы, базы и DAO) и пользовательский интерфейс. По факту, это адаптер или маппер, который преобразует данные, предоставляемые сервисами бизнес логики, в данные, хранящиеся в TweexViewModel.
  4. TweexLiveData и TweexMutableLiveData – интерфесы, которые нужны лишь для того, чтобы позволить отделиться от LiveData из androidx и иметь возможность тестировать все приложение, исключая UI часть с помощью обычных unit тестов без Robolectric и т.п.
  5. CoordinatorContainer – интерфейс для временного хранения работающего Coordinator

Диаграмма компонентов

TweexView при создании создает TweexViewModel, и на основе ее создает соответсвующий Coordinator, который будет единственным на протяжении жизнинног цикла TweexView и для временного хранения (когда активность или фрагмент уничтожены после saveInstanceState) помещается в CoordinatorContainer, для последующего извлечения оттуда при onRestoreInstanceState

components_diagram

Диаграмма взаимодейтвия

На диаграаме ниже представлено взаимодествие компонентов, для выполнения задачи некой загружки данных из сети Интернет. При этом пользователь может не дожидаться загрузки, а просто свернуть приложение на время загрузки (и система даже может уничтожить на это время активность или фрагмент), но загрузка данных продолжиться, и после воостановления окна приложения они будут корректно отображены. При этом нет обходимости перезагружать данные или выполнять какие-либо дополнительные действия, т.к. закэшированные в TweexViewModel данные через Observer отображены на экране.

Возможным минусом данного подхода можно назвать хранение в памяти информации, хотя в данный момент view не отображается. Однако это допущения было принято, в виду того, что зачастую данные необходимые для отображения малы по объему в сравнении с объемами памяти современных устройств. Для более сложных же задач (например картинки или другие данные) скорее всего будут применяться специфические подходы, т.к. данные все равно придется отображать на UI.

Следуюет сказать, что данный подход предполагает, что для хранения менающихся данных внутри TweexViewModel будут использоваться TweexLiveData или обычная *LiveData. *Такой подход позволит обновлять данные на UI и при этом, полями внутри *TweexViewModel *могут быть ссылки на Singleton LiveData или им подобные. Таким образом, можно реагировать на события и изменения происходящие в других частях приложения (например, список файлов для загрузки: файла загружаются в запущеном сервисе или в WorkManager, которые оновляют LiveData, ссылка на которую через Singleton объект является полем в TweexViewModel для данного TweexView)

Также отметим, что если пользователь уходит с активности через back, т.е. она более не нужна, то соответсующий Coordinator и связанная с ним TweexViewModel уничтожаются и не храняться больше в памяти

flow_diagram

Плюсы

  • Восстановление состояния и загруженных данных на onRestoreInstanseState
  • Не заботимся о том (при правильном применении конечно), что потоки загрузки могут вызвать Listeners активности на обновление отдельных view, когда активность уже уничтожена
  • Данные через LiveData/TweexLiveData отображаются на UI в актуальном состоянии
  • Можем писать Unit тесты без использования Robolectrick сделав лишь Mock для TweexView

Недостатки

  • Храним в памяти и выполняем в фоновом потоке логику, для активностей, которые в состоянии **stopped **(но не destoyed).
  • Возможно не самым простым способом можем подключить DI (Dagger, Koin)

Особенноси реализации в библиотеке

В GitHub есть реализация такого подхода, предоставля базовые классы для создания приложений с применением такого подхода (https://github.com/remdevlab/android-rem-wetweex)

Мы назвали библиотеку WeTweex. По размерам она достаточно легковесная, содержит базовые реалиации компонент и некоторые дополнения к ним.

Одним из немаловажных элементов библиотеки является ExecutableTask. Это небольшая обертка с использованием java.util.concurrency.Executor для постороения и выполения некой задачи в фоновом потоке. Результаты задачи можно получить через callback, которые также выполняются в фотовом потоке, а также задачу можно отменить.

ExecutableTask<String> generateStringTask = ExecutableTask.cancellable(
 () -> textGenerator.generateText(1000L).getText()
).onCancel(() -> {
 // do on cancel
}).onSuccess(srting -> {
 // do some with generated string.
}).onError( throwable -> {
 // do some with error
}).onComplete(() -> {
 // called no matter failed or cancelled or succeeded
});

Ни один из onCancel, onSuccess, onError, onComplete не является обязательным. Они будут выполены в случае если они есть. Если их нет, то task выполниться но результат не будет известен.

Библиотека также содержит реализацию интерфейса Coordinator:

  • SimpleCoordinator – реализует интерфейс Coordinator и также предоставляет методы для доступа к выполяемым задачам и ифнормируем о начале/окончании исполения задачи. Основным методом для работы является *submitTask, *который позволяет запустить задачу на исполение.
  • ProgressWatchingCoordinator – наследник SimpleCoordinator, который работает уже с TweexProgressViewModel, что еще хранит в себе минимальную информаию о том, выполянется ли какая-либо задача. В паре с BaseTweexProgressObservingActivity позволяет автоматически отображать Progress Dialog, со списком исполняемых задач.

Типы задач

Задачи, выполняемые в приложении для отображения на UI, можно разделить на 3 группы:

  • Отменяемые – результат не критичен, можем отменить. Например, зарузка файла, поиск.
  • Неотменяемые – задачу нельзя отменять, т.к. это приведет к неправильной работе приложения (отправка нескольких запросов для подтверждения некой транзакции, т.е. не можем отменить в середине).
  • Критические – пока задача не закончится, мы не можем ничего отобразить на экране. Отменяя ее, пользователь скорее всего желает уйти с этого экрана.

В соответсвии с этой классификацией, ExecutableTask предоставляет три статических метода для создания задачи:

  • cancellable
  • nonCancellable
  • crucial

На основании этой классификации, реализация SimpleCoordinator определяет, что делать с текущей задачей, когда пользователь нажимает back и хочет покинуть активность или фрагмент (для этого в реализации TweexActivity есть логика позволяющая при попытке остановить задачу, узнать от coordiator можно ли закрыть экран или отменить задачу).

Тестирование

Для того, чтобы тестировать приложение, написанное подобным образом, можно использовать Mockito и обычные JUnit тесты. Применяя моки для TweexLiveData можно избежать необходимости использования Robolectric. (планируется выпутстить библиотеку wetweex-tests для поддержки тестов и генерации mock на основе TweexLiveData, покрывая ими поля типа TweexLiveData).

Пример

С использованием этой бибилотеки был создан небольшой пример, доступный на GitHub (https://github.com/remdevlab/android-rem-wetweex/tree/master/samples)

About

A small library a kind of architecture pattern implementation for android app's development and some samples

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published