LifestyleHUB – это приложение для формирования собственного досуга и управления им. От поиска интересных мест и мероприятий до получения персональных рекомендаций. Основная цель - помочь клиенту найти, чем заняться в свободное время, изучить новые места и поучаствовать в активностях. Приложение предоставляет все, что поможет сделать выбор и распланировать отдых
-
Для работы с UI был выбран
Jetpack Compose
, а не Android XML. Google активно развивает и продвигает этот инструмент, и в будущем он определенно станет основной технологией верстки, так же как Kotlin заменил Java. Переход к декларативному UI прослеживается во всей мобильной разработке: IOS (переход со сторибордов на swift ui), Flutter, React Native. Я считаю, что Compose достаточно проверенный и современный инструмент, поэтому использую его в этом проекте -
Для работы с API был выбран
Retrofit
. Можно было бы ограничиться только OkHttp, но в Retfrofit очень подкупает легкая кодогенерация. Retrofit дает достаточную гибкость при используемых API сервисов. В будущем будет не сложно если что мигрировать весь код на работу с OkHttp. На данном этапе же Retrofit позволил не тратить много времени на парсинг json, а сконцентрироваться на фичах приложения -
Использовалась библиотека Argon2 для одностороннего хеширования паролей. Она очень легкая, поэтому нет ни одной причины ее не внедрять, раз пароли мы храним прямо на устройстве
-
Google maps. Нужны для вкладки "карта"
- Скопируйте код репозиторий командой
git clone https://github.com/Central-University-IT-prod/mobile-zotovy
- Откройте проект в Android Studio
- Установите все необходимые зависимости (Gradle sync)
- Создайте файл local.properties с содержимым
MAPS_API_KEY=secret
- Можно запускать проект :)
Для сборки apk откройте проект в Android Studio. В тулбаре
найдите Build
> Build Bundles(s) / APK(s)
> Build APK(s)
.
Файл apk появится в папке app/build/output/apk/debug
(или release в зависимости от типа сборки).
Для удобства тестирования забилдил для любимых жюри apk в релизы на гитхабе :)
- По всему приложения были добавлены микроанимации, к примеру при клике элемент немного уменьшается, тем самым реагирует на нажатие и показывает фидбек нажатия юзеру
- Во всем приложение реализованы различные состояния экранов, например "нет доступа к геолокации", "нет доступа к интернету", индикаторы загрузки (в том числе и скелетоны)
- На детальной странице события/места (venue короче) при клике на картинку можно посмотреть ее во весь экран
- На детальной странице события кликабельны контакты (адрес, номер телефона, соц сети). При клике перебрасывает в соответствующее место (в карты, звонок, твиттер и тд)
- На детальной странице события есть список похожих мест. При клике перебрасывает на детальную страницу об этом месте
- Реализована карта интересных мест поблизости с пользователем. При перемещении карты в другое место, места автоматически прогружаются в окрестности взгляда наблюдателя (карты) и кешируются
- При клике на маркер на карте можно перейти на детальную страницу об этом месте
.
├── app/
│ ├── components/
│ ├── modules/
│ │ └── module_name/
│ │ ├── components/
│ │ ├── Screen.kt
│ │ └── ViewModel.kt
│ ├── utils/
│ ├── DI.kt
│ ├── MainActivity.kt
│ └── Router.kt
│
└─── data/
├── api/
├── common/
├── interfaces/
├── mappers/
├── models/
├── repositories/
└── utils/
Проект разбит на 2 модуля: app и data
Основной модуль приложения, так же отвечает и за UI.
components
– верхнеуровневые компоненты, которые могут быть использованы в любой точке приложения. К примеру это кнопка, текстовое поле, индикаторы загрузки и тдmodules
– модули (логично изолированные части приложения). При работе с UI удобно класть в одно место все то, что относится к одной фиче/экрану приложения в одно место, так как чаще всего над этим работает один человек. Внутри каждого модуля обычно есть еще одна папкаcomponents
, в которую кладут компоненты, относящиеся только к данной фиче. Их удобно так выносить, чтобы по пол часа не искать нужный файл. В модуле также обычно лежит какой-то экран и viewmodelutils
– все утилиты и расширения, что непосредственно к фичам не относится, лежит здесьDI.kt
– было глупо в такой проект тащить сложный DI по типу koin или dagger, так как все классы обычно простые синглтоны. Все зависимости вынес в этот объектMainActivity.kt
– так используется compose, на все приложение одно activityRouter.kt
– тут прописана вся конфигурация навигации в приложение
Тут происходит вся работа с данными: получение из интернета, кеширование, локальное хранение
api
– Retrofit интерфейсы для работы с сетьюcommon
– сервисные классы и объекты для инициализации/конфигурации прочих слоевinterfaces
– интерфейсы всех слоев в модули датаmappers
– объекты для трансформации сырых api сущностей в доменные сущностиmodels
– модельки данных/сущностейrepositories
– классы, отвечающие за получение и кэширование данныхutils
– различные вспомогательные утилиты
- Все слои по максимуму используют интерфейсы, а не прямые зависимости для тестируемости кода
- Composable компоненты (за исключением страниц) по максимуму работают с примитивами, а не с другими системными сущностями. К примеру лучше в "VenueCard" передать класс с данными "Venuе" и callback "onClick", чтобы можно было легко писать unit тесты для компонентов. Странице же обычно unit тестами не покрываются
Выбор всего двух модулей, такой архитектуры был выбран осознанно, исходя из размеров приложения. Если приложение будет расти, то можно легко расширять данную архитектуру, выносить в отдельные модули разные фичи, внедрять более совершенные DI. Я считаю, что для поставленной задачи такая архитектура является одной из наиболее оптимальных, предусматривает тестируемость кода и расширение функционала
Была использована одна ветка main
, все сразу пушилось в нее, т.к. над проектом работал один
человек
и сроки были достаточно ограничены. В будущем можно ввести ветку dev
и под каждую отдельную
задачу
создавать новую ветку. Но это все имеет смысл, если поставленные задачи будут меняться со временем,
если придется работать параллельно над несколькими задачами, если будет 2 и более разработчиков.
Так как в текущих условиях все планы сразу поставленны и обозначены, работает один человек, не вижу
причин использовать вторую ветку
При написании сообщений к коммитам используется Conventional Commits
Разработано @zotovy