To-do Flutter приложение, в рамках проектной деятельности во время участия в Школе мобильной разработки Яндекса.
State management: bloc
Dependency injection: dino
Database: hive
Для запуска интеграционных тестов необходимо ввести команду:
flutter pub run melos run integration_test
Для работы с архитектурой (генерации и обновления структур) используется CLI, пока что не опубликованный в открытый доступ. В любом случае, это не мешает компиляции и просмотру кода.
Пользователь взаимодействует с локальной БД приложения, после чего выполняется асинхронная операция синхронизации с API. Это позволяет работать с приложением максимально быстро и плавно, без необходимости ожидания подгрузки информации, либо завершения действий (создания, изменения, удаления задачи).
Если синхронизация не удалась (нет интернета, ошибка сервера и тд), то операция повторяется каждые 5 секунд, пока не окажется успешной.
В состоянии простоя, приложение синхронизирует локальную БД с данными из API каждую минуту. Также синхронизация проводится при открытии приложения, изменении состояния подключения к сети и возврате в приложение из background.
В локальной БД хранятся не только задачи, но и состояния несинхронизированных с API изменений. При синхронизации происходит слияние данных из API с несинхронизированными изменениями из локальной БД.
Решение конфликтов при слиянии происходит по стратегии, направленной на минимализацию возможного ущерба. Это позволяет отменить удаление задач, если экземляр задачи в синхронизированной копии на сервере окажется более актуальным, чем в локальной копии (либо наоборот, на устройстве актуальнее чем на сервере), в которой была запрошена операция удаления.
Например, если пользователь удалил задачу на устройстве 1
без доступа к сети, а на устройстве 2
, которое может синхронизироваться с API, изменил данную задачу, то при следующей успешной синхронизации на устройстве 1
удаление будет отменено, что позволит не потерять актуальные изменения.
Также, если на устройстве с доступом к сети удалить задачу, а потом внести изменения в экземпляре данной задачи на другом устройстве, и провести синхронизацию с API, то задача будет восстановлена на сервере.
Адреса:
- Список задач: todoapp://todoapp/
- Открыть задачу по id: todoapp://todoapp/task/:taskId
- Открыть окно создания задачи: todoapp://todoapp/task/create
Структура проекта представляет собой монорепозиторий (workflow), состоящий из нескольких модулей (app, core, task).
Каждый модуль в свою очередь состоит из трёх слоёв: domain, infrastructure и presentation. Каждый слой находится в отдельном пакете и имеет строго определенные зависимости от других слоёв.
Всего выделяется три слоя:
- domain: самый чистый слой, содержащий модели и сервисы предметной области, иными словами, наиболее чистую бизнес-логику;
- presentation: слой, представляющий графическую составляющую приложения и логику взаимодействия с пользователем. Может содержать виджеты, страницы и сервисы, необходимые для этого слоя. Зависит от слоя domain и использует его публичные сервисы для реализации пользовательского опыта;
- infrastructure: слой, зависящий от всех остальных слоёв и имеющий наиболее полную картину всего модуля. В нём реализуются некоторые сервисы предметной области и слоя презентации, которые нельзя или не следует реализовывать там, где они объявлены. Например, в этом слое происходит всё взаимодействие с внешними источниками данных: их получение, отправка, маппинг.
Изоляция слоёв с помощью пакетов позволяет в полной мере задействовать принцип инверсии зависимостей на практике: невозможно использовать сервис или модель в том слоё, для которого она не предназначена по Dependency Rule.
Каждый слой имеет свой Pubspec файл, что позволяет использовать зависимости из pub.dev только в тех местах, где это нужно. Можно также прописывать и зависимости между слоями, но для автоматизации и предотвращении ошибок используется CLI, генерирующий pubspec_overrides.yaml на основе modulespec.yaml, который находится в корне каждого модуля.
Модули также могут зависеть друг от друга. Тогда слои зависимого модуля соответственно зависят от слоёв модуля-зависимости.
Модули app и core являются обязательными и генерируются автоматически. Модуль core является зависимостью для всех остальных слоев, а модуль app нужен для того, чтобы интегрировать другие модули, если нет возможности создать для интеграции отдельный модуль.
Помимо модулей, в проекте также есть пакет todo_app, который является точкой входа. Он импортирует все модули, задействованные в приложении (все их слои) и собирает в итоговое приложение. По сути это и есть основной пакет приложения, поэтому в Pubspec файле проекта можно указать основную информацию — описание приложения, версию.
- Тёмная тема
- Локализация
- Navigator 2.0
- Firebase App Distribution
- Firebase Crashlytics
- Remote Config: переключение цвета важности
- Firebase Analytics
- Анимации
- Поддержка горизонтальной ориентации
- Deeplink
- Поддержка больших экранов
- Unit-тесты
- Интеграционные тесты
- Flavors (Testing, Production)