NOTE: For Kotlin version of this app, navigate to: https://github.com/mrmitew/BodyLog-Kotlin
The main goal of this (WIP) project is to demonstrate an implementation of the Model-View-Intent (MVI) design pattern, which aims at having a unidirectional data flow where application state is driven by the business logic.
The project follows the "clean" approach for architecting apps and is composed of several modules (both Android and pure java), namely:
- framework (UI)
- data (Repository)
- adapter (UI presentation)
- domain (Business logic)
Presenter(s) in this implementaion have no lifecycle. They implement the Disposable interface and expose couple of additional methods, including bindIntents(), unbindIntents() and optionally attachView(View) and detachView().
Internally, Presenters create PublishRelay, which subscribes to the stream of View intents and serve as a gateway to the business logic of the app. Communication between Presenter and business logic is established by using *Interactor*s which can also be shared between other *Presenter*s. When there is a screen orientation change, View detaches from Presenter by unsubscribing the PublishRelay from the View. When the View attaches back to the Presenter, the PublishRelay subscribes back to the View's stream of intents.
In addition, presenters create BehaviourRelay(s) that work as a gateway from business logic to View. While a View is detached from a Presenter, say we navigate forward from Activity A to Activity B, the presenter of Activity A will be still alive and can receive updates from the business logic. When we navigate back and View reataches to Presenter, the BehaviourRelay will replay the cached model update and View will update accordingly.
In order to preserve a Presenter in memory during orientation change, it is injected into a PresenterHolder which extends from Android's ViewModel (https://developer.android.com/topic/libraries/architecture/viewmodel.html). Throughout the lifecycle of an activity/fragment, View(s) get detached and reatached to Presenter(s), so no memory leaks would occur. When an Activity or Fragment gets finally destroyed (not due to orientation change), Presenter is also destroyed, since the hosting ViewModel (PresenterHolder) gets garbage collected.
- AppCompat
- Butterknife
- RxJava2
- RxAndroid
- RxRelay2
- Lifecycle (for Android's ViewModel)
- Dagger (dependency injection)
- AutoValue (immutability)
- LeakCanary (finding memory leaks)
- JUnit
- Mockito