For those of you interested in skipping the article, this is the GitHub link.
So let’s begin!
I have used Hilt and KSP (Kotlin Symbol Processing — similar to KAPT) for injecting our data layer with our UI layer. The other libraries used here are Room library for storing and retrieving the notes from the local db and gson converter for serialisation.
I have also used Gradle’s version catalogs to declare dependencies in the app. You can checkout my other articles on version catalogs and Hilt to get a deeper understanding of what is required here. For now, I’ll just share the relevant files used to add these dependencies.
We also need to create a custom Application
class and annotate it with @HiltAndroidApp
and add it to our Manifest file.
Now that we have our dependencies, we need to create a model class that holds our Note
data.
We should be able to create our Dao
and Database
class using Room.
We also create a Repository
class that interacts with the NoteDao
class to fetch/add/update/delete notes from the db.
The NoteUiViewState
class is the single source of truth for the UI in the notes list screen. It holds all the necessary data required to represent the current state of the UI.
The NoteIntent
sealed class encapsulates all the possible actions a user can take on the app. Each intent is a specific user interaction that leads to a change in the application state.
The NotesViewModel
class plays a crucial role in managing the UI’s state and handling user interactions in an MVI-based architecture. It inherits from the ViewModel
class, which provides lifecycle awareness and makes it possible to manage UI-related data efficiently, especially during configuration changes like screen rotations.
In addition to managing the state, the ViewModel handles one-time events (or side effects) such as displaying a snackbar message or redirecting to the detail screen, using a Channel
. Since these one-time events will be application wide, we are creating an EventManager
class.
The MainApp
composable is the central piece of the notes app UI. It is responsible for rendering the entire UI and interacting with the ViewModel to reflect the application’s current state. This composable follows MVI principles, ensuring a unidirectional data flow and handling state management and effects (like snackbar notifications) in a reactive manner.
The NotesScreen
composable observes the state changes from the ViewModel
and updates the UI reactively.
The NoteItem
composable implementation can be found here and the entire implementation can be found here.