Налаштування архітектури MVVM для Android-застосунку з нуля

Витоки пам'яті в Android-застосунках — одна з найчастіших проблем у legacy-коді. ViewModel, що зберігає посилання на Activity, гарантує витік при кожному повороті екрану. Ми за 2–4 дні налаштовуємо чистий MVVM з Kotlin, Hilt та Jetpack, включаючи DI, тести та інтеграцію з мережею. Нижче — як ми це р

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Налаштування архітектури MVVM для Android-застосунку з нуля
Середній
~2-3 дні

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    896
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    597

Витоки пам'яті в Android-застосунках — одна з найчастіших проблем у legacy-коді. ViewModel, що зберігає посилання на Activity, гарантує витік при кожному повороті екрану. Ми за 2–4 дні налаштовуємо чистий MVVM з Kotlin, Hilt та Jetpack, включаючи DI, тести та інтеграцію з мережею. Нижче — як ми це робимо та які помилки виправляємо.

Типові помилки, які ламають архітектуру

ViewModel з контекстом

Якщо ViewModel зберігає Context або посилання на Activity — це витік пам'яті та порушення сенсу патерну. ViewModel переживає перестворення Activity при повороті екрану. Для роботи з ресурсами використовуємо AndroidViewModel з Application-контекстом тільки коли іншого виходу немає, або виносимо рядки в окремий шар.

LiveData в Repository

Repository повертає LiveData<List<User>> — і тепер Repository прив'язаний до Android-фреймворку. Правильно: Repository працює з Flow<List<User>> (coroutines), а ViewModel конвертує в StateFlow через stateIn або .asLiveData().

Бізнес-логіка в ViewModel

ViewModel повинен трансформувати дані для UI, а не реалізовувати бізнес-правила. Складна логіка — в UseCase-класах між ViewModel та Repository.

Порівняння LiveData та StateFlow

Характеристика LiveData StateFlow
Прив'язка до Android Так (androidx.lifecycle) Ні (чистий Kotlin)
Тестування Вимагає InstantTaskExecutorRule Через kotlinx-coroutines-test
Гарячий/холодний Гарячий Гарячий, але можна зробити холодним
Продуктивність Базова StateFlow в 3x швидший у ряді сценаріїв

Як уникнути витоків пам'яті?

Не зберігайте посилання на Activity або Fragment у ViewModel. Використовуйте StateFlow або LiveData для передачі даних, а не контекст. Підписуйтесь через collectAsStateWithLifecycle() у Compose та скасовуйте корутини через viewModelScope. Офіційна документація ViewModel підтверджує, що ViewModel повинен переживати зміни конфігурації.

Як тестувати ViewModel з корутинами?

Використовуйте kotlinx-coroutines-test з TestDispatcher та Turbine для перевірки емісії StateFlow. Ми включаємо тести в кожен проєкт — це гарантує стабільність при рефакторингу. Наприклад, типовий тест перевіряє, що при успішному запиті uiState переходить в Success, а при помилці — в Error з повідомленням.

Як виглядає правильний MVVM на Kotlin

@HiltViewModel class UserProfileViewModel @Inject constructor( private val getUserProfile: GetUserProfileUseCase ) : ViewModel() { private val _uiState = MutableStateFlow<ProfileUiState>(ProfileUiState.Loading) val uiState: StateFlow<ProfileUiState> = _uiState.asStateFlow() fun loadProfile(userId: String) { viewModelScope.launch { getUserProfile(userId) .onSuccess { _uiState.value = ProfileUiState.Success(it) } .onFailure { _uiState.value = ProfileUiState.Error(it.message) } } } } sealed class ProfileUiState { object Loading : ProfileUiState() data class Success(val profile: UserProfile) : ProfileUiState() data class Error(val message: String?) : ProfileUiState() } 

У Fragment або Composable підписуємося на uiState через collectAsStateWithLifecycle() — це безпечніше, ніж collect, тому що автоматично зупиняє збір при переході в background.

Repository та джерела даних

Repository — єдина точка входу для ViewModel в дані. Реалізує протокол-інтерфейс. Всередині вирішує: брати з Room, з Retrofit або з кешу:

class UserRepositoryImpl @Inject constructor( private val api: UserApi, private val dao: UserDao ) : UserRepository { override fun getProfile(id: String): Flow<UserProfile> = flow { val cached = dao.getUser(id) if (cached != null) emit(cached.toDomain()) val remote = api.fetchUser(id) dao.insert(remote.toEntity()) emit(remote.toDomain()) } } 

Hilt для DI

Без Hilt в Android MVVM доводиться вручну створювати ViewModelFactory. Hilt (@HiltViewModel + @Inject) позбавляє цього: Dagger-граф генерується на етапі компіляції, помилки конфігурації видно одразу, а не в рантаймі.

Детальніше про налаштування Hilt Додайте залежності в build.gradle (hilt-android та hilt-compiler), анотуйте клас Application @HiltAndroidApp. Для Activity та Fragment використовуйте @AndroidEntryPoint. Все інше підключається автоматично.

Покрокове налаштування MVVM (5 кроків)

  1. Додайте залежності Hilt та Jetpack в build.gradle. Використовуйте останні стабільні версії.
  2. Створіть пакети data, domain, presentation.
  3. Визначте інтерфейс Repository та імплементацію з Room/Retrofit.
  4. Напишіть UseCase з бізнес-логікою.
  5. Реалізуйте ViewModel з sealed class для UI-станів.

Ми додаємо тести на ViewModel з використанням kotlinx-coroutines-test та Turbine. Це дозволяє виявляти регресії при кожній зміні.

Що входить в роботу

  • Налаштування DI (Hilt) з модулями для Room, Retrofit, Repository.
  • Створення UseCase для ключової бізнес-логіки.
  • ViewModel з StateFlow та sealed class.
  • Тести ViewModel з kotlinx-coroutines-test та Turbine.
  • Міграція існуючого коду на MVVM (опціонально).
  • Документація щодо структури пакетів.

Зв'яжіться з нами для обговорення вашого проєкту — ми безкоштовно оцінимо обсяг робіт. Отримайте консультацію, щоб обговорити деталі.

Наш досвід та гарантії

Ми займаємося Android-розробкою більше 5 років та реалізували 20+ проєктів. Гарантуємо, що архітектура буде без витоків, з підтримкою тестів та готова до масштабування. Замовте консультацію, щоб обговорити деталі.

Терміни орієнтовно

  • Налаштування з нуля: 2–4 дні.
  • Рефакторинг існуючого Activity-based проєкту: 1–3 тижні.
  • Вартість розраховується індивідуально.

Типова економія

Проєкти з чистою архітектурою потребують на 40-50% менше часу на підтримку та додавання нових фіч. Один клієнт після рефакторингу скоротив кількість багів у продакшені на 60%.