Boilerplate code for implementing MVVM in Android using Jetpack libraries, coroutines, dependency injection and local persistance

Overview

MVVM Foundation

This projects aims to speed up development of Android apps by providing a solid base to extend

Libraries

  • Jetpack Fragment
  • Material3 : for UI components and theming.
  • ViewPager2 : for ViewPager UI component. Used in sliding tabs.
  • EasyBinding : Abstract classes for Activities and Fragments that use viewBinding.
  • Hilt : dependency injection.
  • Room : local SQLite database.
  • RxJava3 : reactive programming in Android (so far not used, but good to have for the future).

Architecture

├── BaseApplication.kt
├── constants
│   └── NavigationConstants.kt
├── di_modules
│   ├── DatabaseModule.kt
│   └── DispatcherModule.kt
├── MainActivity.kt
├── model
│   ├── database
│   │   ├── AppDatabase.kt
│   │   ├── entities
│   │   │   └── TimeRecord.kt
│   │   └── TimeRecordsDao.kt
│   └── repository
│       └── TimeRecordsRepository.kt
├── view
│   ├── ButtonControlsFragment.kt
│   ├── FeedFragment.kt
│   └── navigation
│       └── ViewPagerAdapter.kt
└── viewmodel
    └── ButtonControlsViewModel.kt
  • BaseApplication is the entry point to the app. Annotated with @HiltAndroidApp to use dependency injection.
  • constants contains constants.
  • di_modules contains dependency injection providers (When Hilt is unable to figure out a dependency to inject, create a module to explicitly define how to provide the dependency).
  • model contains data related logic and infrastructure.
    • database contains classes related to database.
      • entities are data classes used by the database.
    • repoitory contains repositories (used to abstract database operations).
  • view contains Activities, Fragments and related UI classes (adapters, viewholders, etc).
  • viewmodel contains viewModels.

How does this work

Consider we need to show a list of TimeRecords (provided entity) in FeedFragment

  1. TimeRecordsDao defines a method for retrieving the list from the database TimeRecordsDao.getAll() : List<TimeRecord> by executing an annotated SQL query.
  2. TimeRecordsRepository defines a method TimeRecordsRepository.getAllRecords(): List<TimeRecord> that calls the Dao method with a Dispatcher Context (to avoid blocking the UI thread).
  3. ButtonControlsViewModel creates a coroutine ButtonControlsViewModel.getAllRecords() that calls the repository method within a coroutineScope and posts results to timeRecordsLiveData.
  4. FeedFragment observes ButtonControlsViewModel.timeRecordsLiveData and reacts to changes in the data, updating the UI.
  5. ButtonControlsFragment calls ButtonControlsViewModel.getAllRecords() to start the flow

Takeaways

  • The Dao is an interface that provides abstract suspend functions to communicate (execute queries) with the Database. Methods do not have a body, the annotation generates the code under the hood.
  • The Repository knows nothing about the Database, it only knows what the injected Dao can do and defines the injected Dispatcher to use.
  • The ViewModel knows nothing about the Dao, it only knows the methods that the injected Repository can provide and creates coroutines.
  • The ViewModel knows nothing about the View either, it uses callbacks to interact with Activities/Fragments and liveData to provide data to the observers (Activities/Fragments).
  • The View only knows about the ViewModel, it has absolutely no idea regarding the Database or the Repository.
  • This separation of concerns allows us to change specific components (for example, the Dispatcher injected to the Repository or the Repository injected to the ViewModel) with ease.
  • Sharing ViewModels across Fragments/Activities allows sharing state and methods (we call getDataAllRecords() in ButtonControlsFragment and observe the state changes results on FeedFragment)
  • Dependency injection (di) allows to change/update dependencies with less code and less memory allocation. For instance, we need the same instance of ButtonControlsViewModel for FeedFragment and ButtonControlsFragment, so we inject the ViewModel in the activity scope byActivityViewModels() to make the same instance available for both fragments. Without Hilt sharing a ViewModel in this case would require to make it a Singleton (and implement the singleton logic)
You might also like...
A fork of our clean architecture boilerplate using the Model-View-Intent pattern

Android Clean Architecture MVI Boilerplate Note: This is a fork of our original Clean Architecture Boilerplate, except in this repo we have switched o

Android project setup files when developing apps from scratch. The codebase uses lates jetpack libraries and MVVM repository architecture for setting up high performance apps

Android architecture app Includes the following Android Respository architecture MVVM Jepack libraries Carousel view Kotlin Kotlin Flow and Livedata P

Recycler-coroutines - RecyclerView Auto Add Data Using Coroutines

Sample RecyclerView Auto Add With Coroutine Colaborator Very open to anyone, I'l

Minecraft 1.18.2 Backport of Petal, a performance-oriented fork of Purpur intended to increase performance for entity-heavy servers by implementing multi-threaded and asynchronous improvements.

Sakura Performance Minecraft JAR Sakura is a performance-oriented fork of Purpur intended to increase performance for entity-heavy servers by implemen

A Kotlin library for reactive and boilerplate-free SharedPreferences in Android
A Kotlin library for reactive and boilerplate-free SharedPreferences in Android

KPreferences A Kotlin library for reactive and boilerplate-free Shared Preferences in Android. With KPreferences you can use Kotlin's marvelous delega

An Android template project (in Kotlin) with boilerplate and current patterns.

android-starter-v4 An Android template project (in Kotlin) with boilerplate and plumbing, exploring current architecture patterns. A bit too much for

Android-Boilerplate - Base project for android development with new technology

Android-Boilerplate Base project for android development with new technology, in

Example Multi module architecture Android project using MVVM, Dynamic Features, Dagger-Hilt, Coroutines and Navigation Components
Example Multi module architecture Android project using MVVM, Dynamic Features, Dagger-Hilt, Coroutines and Navigation Components

ModularDynamicFeatureHilt An Android template project following a multi module approach with clean architecture. It has been built following Clean Arc

🪐 Modern Android development with Hilt, Coroutines, Flow, JetPack(ViewModel) based on MVVM architecture.

Ceres 🪐 Modern Android development with Hilt, Coroutines, Flow, JetPack(ViewModel) based on MVVM architecture. Download Gradle Add the dependency bel

Owner
Gabriel Gonzalez
Programmer. Mobile and web developer. Highly social geek. Passionate for art and technology
Gabriel Gonzalez
🍭 GithubSearchKMM - Github Repos Search - Android - iOS - Kotlin Multiplatform Mobile using Jetpack Compose, SwiftUI, FlowRedux, Coroutines Flow, Dagger Hilt, Koin Dependency Injection, shared KMP ViewModel, Clean Architecture

GithubSearchKMM Github Repos Search - Kotlin Multiplatform Mobile using Jetpack Compose, SwiftUI, FlowRedux, Coroutines Flow, Dagger Hilt, Koin Depend

Petrus Nguyễn Thái Học 50 Jan 7, 2023
Dependency Injection library for Kotlin Multiplatform, support iOS and Android

Multiplatform-DI library for Kotlin Multiplatform Lightweight dependency injection framework for Kotlin Multiplatform application Dependency injection

Anna Zharkova 32 Nov 10, 2022
Lightweight Kotlin DSL dependency injection library

Warehouse DSL Warehouse is a lightweight Kotlin DSL dependency injection library this library has an extremely faster learning curve and more human fr

Osama Raddad 18 Jul 17, 2022
Dependency Injection library for Compose Multiplatform, Koin wrapper.

?? Cokoin Injection library for Compose (Multiplatform and Jetpack), Koin wrapper. It uses @Composable functions to configure KoinContext and Scopes.

Bruno Wieczorek 57 Dec 29, 2022
A personal project made using Jetpack Compose, Clean-MVVM architecture and other jetpack libraries

A basic CRUD for recording your personal credit and debit transactions. Made using Jetpack Compose, Clean-MVVM and other Jetpack libraries, incorporated with Unit Tests.

Shoaib Ahmed 3 Dec 6, 2022
👋 A common toolkit (utils) ⚒️ built to help you further reduce Kotlin boilerplate code and improve development efficiency. Do you think 'kotlin-stdlib' or 'android-ktx' is not sweet enough? You need this! 🍭

Toolkit [ ?? Work in progress ⛏ ?? ??️ ?? ] Snapshot version: repositories { maven("https://s01.oss.sonatype.org/content/repositories/snapshots") }

凛 35 Jul 23, 2022
Automatic CoroutineDispatcher injection and extensions for kotlinx.coroutines

Dispatch Utilities for kotlinx.coroutines which make them type-safe, easier to test, and more expressive. Use the predefined types and factories or de

Rick Busarow 132 Dec 9, 2022
A fork of our clean architecture boilerplate, this time using the Android Architecture Components

Android Clean Architecture Components Boilerplate Note: This is a fork of our original Clean Architecture Boilerplate, except in this repo we have swi

Buffer 1.3k Jan 3, 2023
An android boilerplate project using clean architecture

Android Clean Architecture Boilerplate Welcome ?? We hope this boilerplate is not only helpful to other developers, but also that it helps to educate

Buffer 3.6k Jan 4, 2023