Application that downloads and renders CV of mine.
- Displaying list of CV items (photo, summary, personal development, job positions and hobbies).
- Navigating to social media links (Medium, StackOverflow, YouTube)
View
(Activity) is responsible for gluing ViewModel
class with rendering function. Besides, it is responsible for sending intention actions that can be anything like user interaction or system callbacks. The View
should not contain any rendering, business logic.
A Renderer is a simple class that uses RecyclerView
as the main render engine. It has two main responsibilities:
- Setup
RecyclerView
with correct adapter class. - Transform immutable view state to adapter items and render them on the screen.
Render function has to be pure! It cannot use any properties outside of its scope. To simplify working with
RecyclerView
I use Groupie library. It also makes rendering logic more declarative.
ViewModel
has a definition of supported intentions. Every action that View
sends to the ViewModel
has to be declared as intention.
Intention reacts to the action with action transformation that produces unique status. In this case transformation is a backend call that downloads CV data. Transformed data are not ready to be displayed so intention uses reduction function to generate new immutable state. A new
state is pushed to the View
layer and renders there. All intention actions are transformed asynchronously and that is baked into ConnectableViewModel.
A function that transforms Action to Status data. Can be a backend call that returns data or fire and forget command like database save/update operation.
A pure function that reduces the current state of the screen using transformation status data.
Dependency Inversion is implemented with the Koin dependency injection framework. It simplifies the separation of objects' creations and their usages. In addition, Koin has a pretty
easy integration with Architecture Component's ViewModel
class so it simplifies gluing it with view layer.
The code is structured using "package by feature" approach. The main reason for such packaging is to imitate app domain structure into the code.
Project has two modules:
:mvi
module that contains helper classes for unidirectional flow architecture (Android library module).:app
module that contains the application logic and screens (Android application module).
Codebase is tested using two different strategies:
- Business logic and Repository is tested using jUnit 5 tests.
- Rendering logic is tested using Robolectric jUnit 4 tests.
Stable build with: Android Studio 3.6.2 Build #AI-192.7142.36.36.6308749, built on March 18, 2020
- Koin to separate object creation from object usages.
- Kotlin Coroutines to run transformations and reductions asynchronously.