Приложение A#

Ключевые усложнения нативного SDK#

  • Несогласованные фоновые операции
    REST-запрос стартовал в IO, запись в SQLite — в Default, обратное уведомление пришло в mainThread. Малейшая задержка вызывала гонку и слепой интерфейс.

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

  • Boilerplate
    Room → Repository → UseCase → ViewModel → LiveData → Compose. Каждая сущность дублирует набор полей — правка трёх строк превращалась в десять правок и pull-request на 200 строк.

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

  • Трудная интеграция железа
    Камера, NFC, голосовой ввод требовали кастомных сервисов, контекстных разрешений и многословного DI-кода.

Детальное описание преодолённых усложнений#

Усложнение

Решение, предоставляемое GlobalErp Mobile Framework

Последовательное выполнение долгих операций блокирует UI

Вся логика БД, сетевые вызовы и файловые операции выполняются в едином серверном потоке. Поток UI занят только отрисовкой.

Race condition между результатами запросов

Подписка осуществляется на ObservableRecord; события доставляются строго в порядке фиксации транзакции.

Разрозненные реализации retry-логики для REST, файлов и локальной БД

Pkg, Api, FileManager работают внутри той же транзакции GsSession. commit / rollback выполняются единообразно.

Сложность атомарного отката: часть данных уже записана, часть — нет

GsSession объединяет БД, файлы, сеть и любые пакеты, созданные пользователем: единая транзакция обеспечивает согласованный откат.

Отмена длительной операции оставляет систему в непредсказуемом состоянии

InterruptingLock прерывает SQL, REST и вычисления; стек состояний автоматически откатывается к стабильному экрану.

Навигация разбросана между Activity, флагами back stack и коллбэками

Стек-ориентированная навигация (SmState + SmTrans) управляется на серверном потоке.
Решения о переходах принимаются до синхронизации с UI.

Передача данных между слоями требует множества Mapper / Repository / ViewModel

Цепочка SQL → RecordSet → Compose избавляет от промежуточных слоёв. Данные приходят в UI напрямую.

Хрупкий офлайн-режим, необходимость писать очередь синхронизации

Все изменения фиксируются локально; синхронизация с сервером оформляется единообразно через очереди задач и Flow, без разрозненных сервисов.

Сложная интеграция аппаратных функций (камера, NFC, QR-сканер)

Плагины ActivityPlugin подключаются в GsBaseActivity. Дополнительных DI-конфигураций не требуется.

Несогласованная обработка аппаратной кнопки «Назад» и жестов

Navigator централизованно управляет TopBar, BottomBar, FAB и back-навигацией для всех экранов.

Невозможность гарантировать порядок выполнения фоновых задач при навигации

Задачи (postSharedTask, postAsyncTask) регистрируются в очереди событий State Manager. Выполняются строго после завершения предыдущих транзакций.

Отсутствие единых правил для тестирования

State / VCI можно запускать с параметром database = null; достаточно