Введение#

Ключевые возможности#

  • Перенос вычислений в серверный поток
    Главный поток никогда не блокируется: фрейм-рендер выполнился — задача ушла в очередь, анимация пользовательского интерфейса не зависит от бизнес-логики.

  • Хранение данных

  • Транзакционная обработка данных GsSession:

    • SQLite, файлы, сетевые отклики — коммитятся или откатываются одним вызовом.

    • Встроенный генератор ID и горячий кэш сущностей.

  • Автоматизация работы с инъекциями зависимостей

  • Адаптированный MVVM-паттерн

  • Навигация между представлениями

  • Планирование серверных команд
    Позволяет избавиться от сложных асинхронных запусков.

  • Observable-слой данных
    RecordSet, SingleRecord, RecordValue<T> передают изменения сразу в Compose-дерево, без необходимости писать адаптеры.

  • Плагин-подход к железу
    ActivityPlugin регистрируется в GsBaseActivity; доступ к NFC или камере получаем без Dagger/Hilt.

  • Горячий офлайн
    Легко настраивать работу, копить данные и синхронизировать по необходимости
    за счёт встроенной поддержки БД.

  • Простое тестирование
    State/VCI можно запустить с database = null, логика тестируется без Android-эмулятора, при этом транзакционная модель сохраняется.

Архитектура#

Взаимодействие слоев#

Взаимодействие слоев

Основные понятия#

  • Главный поток (mainThread) — поток взаимодействия с пользователем; этот поток не должен блокироваться. Рендерит Compose, обрабатывает жесты и никогда не исполняет длительных операций.

  • Серверный поток (serverThread) — поток для выполнения синхронной бизнес-логики и синхронизации с асинхронными задачами. Последовательно выполняет SQL, операции с файлами, трансформации стека и любые другие долгие операции. Все вызовы VCI к тяжёлым ресурсам отправляются сюда через postSharedTask или postAsyncTask (минуют карусель событий).

  • Сессия (GsSession) — сессия работы с данными.
    Содержит контекст для хранения и управления компонентами, необходимыми для обработки данных.

  • Состояние (State) — содержит данные и бизнес-логику представления, работающую в серверном потоке.

  • Стек состояний — хранит историю открытых представлений. Верхнее представление отображается на экране.
    Позволяет пользователю возвращаться на предыдущее представление.

  • Контроллер представления (VCI) — содержит данные и бизнес-логику представления в главном потоке.

  • Представление (VcpScreen) — декларация правил отрисовки представления с использованием библиотеки Compose.

  • Контроллер сессии (Api, Pkg) — контроллер сессии обрабатывает бизнес-логику в серверном потоке в разрезе сущностей базы данных или их групп.

  • Навигатор (Navigator) — занимается компоновкой и управлением представлениями приложения.

  • Главная активность (MainActivity) — точка входа Android-приложения, подробнее смотрите руководство по разработке на платформе Android.

Отдельный серверный поток#

Отдельный серверный поток для выполнения бизнес-логики лучше, чем рассыпанные потоки launch(Dispatchers.IO), так как позволяет достичь:

  • более высокой производительности на последовательных вычислениях за счёт отсутствия необходимости
    межпотоковой синхронизации;

  • более простой разработки и отладки за счёт:

    • последовательного выполнения, что позволяет использовать классические принципы структурного программирования;

    • полностью воспроизводимого stack trace —
      нет прыжков между диспатчерами;

    • декларативной двусторонней синхронизации между главным и серверным потоком;

    • контролируемой отмены:
      InterruptingLock.validate() бросит исключение на любой стадии, стек откатится, а UI мирно вернётся к последнему стабильному экрану.

Адаптированный MVVM-паттерн#

Обеспечивает:

  • Предсказуемый интерфейс
    Стабильный FPS даже на сложных формах.

  • Единый стиль
    Все экраны одинаково устроены, code review смотрит в основном на логику, а не на повторяющиеся слои.

Детализация принципа view–viewmodel–model:

  • View — декларация интерфейса на Compose-UI, объявляется в VCI.

  • viewmodel — разбит на 2 слоя для отделения бизнес-логики главного и серверного потоков:

    • VCI — бизнес-логика для работы в главном потоке, а также подписка на данные state.

    • State — бизнес-логика для работы в серверном потоке, а также сбор данных для представления.

  • model:

    • Api — контроллер таблицы для обработки хранимых данных;

    • Entity — модель хранимых данных.

Жизненный цикл экранов#

Таблица ниже отображает карусель событий, которые произойдут при открытии и закрытии экрана.

Событие

Когда вызывается

Что делать

onInit(State, VCI)

Сразу после создания, синхронно

Подготовить запросы к БД, инициализировать RecordSet

afterPush(State)

State помещён в стек

Подписаться на шину, запустить лёгкие preload-задачи

onVisit() : SmTrans(State)

Сразу после push, но до afterEnter

Вернуть SmTrans для мгновенного перенаправления (например Splash → Login) или null

afterEnter(State)

Каждый раз, когда State стал активным

Обновить данные, запустить postSharedTask; триггерится на каждую фоновую задачу

afterEnter(VCI)

UI создан и синхронизирован с главным потоком

Восстановить scroll-позицию, открыть диалоги, получить данные из State — главная точка синхронизации перед показом экрана

beforeExit(VCI)

UI ещё на экране, но пользователь уходит

Сохранить scroll, закрыть диалоги, очистить временные данные

beforeExit(State)

UI уже закрыт, транзакция ещё открыта

flush() RecordSet, финальные изменения в БД, подготовка к уходу

onError(e)(State)

Любая необработанная ошибка внутри State

Вернуть SmTrans на экран ошибки или кастомизировать обработку

onClose(State)

State удалён из стека окончательно

Отписаться от шины, освободить ресурсы

Дополнительные понятия#

  • Менеджер состояний(StateManager) - отвечает за обработку очереди событий для серверного потока и транзакционной логики обработки переходов между состояниями. StateManager обращается к UI из серверного потока безопасно через блокировки, поэтому состояние стека остаётся консистентным.

Тестирование и масштабирование#

  • Любой State и VCI можно запустить с database = null логика тестируется без эмулятора, транзакционная модель при этом сохраняется.

  • Новый экран требует три файла — State, VCI, Compose-View — и не затрагивает существующий код; команда растёт линейно, не переписывая инфраструктуру.