Architecture guidelines
July 8, 2016 · View on GitHub
Introduction
The architecture of my projects is mixed of MVP (Model-View-Presenter) and MVVM (Model-View-ViewModel) pattern. It is super inspired by Android Architecture Blueprints - powered by Google and community. The architecture doesn't follow a strict MVVM or a pattern, as it uses both View Models and Presenters.
With this architecture, it is mixed of the todo-mvp-databinding, todo-mvp-dagger, todo-mvp-rxjava. Consider to see these repositories before continuing to read.
Key Concepts
Dagger2
Dagger2 is a fully static, compile-time dependency injection framework for both Java and Android. It is an adaptation of an earlier version created by Square and now maintained by Google.
Dependency injection frameworks take charge of object creation. For example, in project we create the TasksPresenter in TasksActivity:
mTasksPresenter = new TasksPresenter(
Injection.provideTasksRepository(getApplicationContext()), tasksFragment);
But in this sample, the presenter is injected. Dagger2 takes care of creation and figuring out the dependencies:
public class TasksActivity extends AppCompatActivity {
@Inject TasksPresenter mTasksPresenter;
...
}
Data Binding
The Data Binding saves on boilerplate code allowing UI elements to be bound to a property in a data model.
- Layout files are used to bind data to UI elements
- Events are also bound with an action handler
- Data can be observed and set up to be updated automatically when needed
Implementation
Architecture preview
Architecture Summary

Architecture Detail Implementation

Key Concepts
-
View (UI layer): this is where Activities, Fragments, and other standard Android components live. It's responsible for displaying the data received from the presenters to the user (via
Viewinterface, or notify changes to Android View (e.g. xml layout) viaviewmodel). It also handles user interactions and inputs (click listeners, etc.) and triggers the right action in the Presenter if needed.In this layer, I use the
databindingframework of Google to bind views, trigger action toPresenterand observe data changes fromviewmodel. Each activity/fragment should be included in a dagger component (i.e.@Component). -
Presenter: presenters subscribe to RxJava Observables provided by the
Repository. They are in charge of handling the subscription lifecycle, analyzing/modifying the data returned by theRepositoryand calling the appropriate methods in the View to display the data.The Presenter instance is created in
@Moduleof each activity/fragment and is provided by using in@Component. ThePresentershould have@Scopeis appropriate by the activity lifecycle (e.g.@PerActivity,PerFragment). It subscribes to observables provided by the appropriateRepositoryand process the data in order to call the right method in theViewor set value toviewmodelto notify the view. -
Model (Data Layer): this is responsible for retrieving, saving, caching and massaging data. It can communicate with local databases and other data stores as well as with restful APIs or third party SDKs, cloud APIs. It is divided in two parts: a
data sourceandhelperspart.-
Data Source
The
data sourcetakes care of business logic. It's the heart of this architecture. It is divided in two parts:local data sourceandremote data source.localwill handle all function and logic related to local data (dics, database (sqlite),SharedPreferenced).remotepart will handle all logic, request and retrieve data from cloud APIs, restful APIs, etc. It keeps a reference to every helper class and uses them to satisfy the requests coming from the presenters. Its methods make extensive use of Rx operators to combine, transform or filter the output coming from the helpers in order to generate the desired output ready for the Presenters. It returns observables that emit data models.Both are injected into a single
repositoryinstance that provide methods to request the appropriate data. Therepositoryand alsodata sourceinstance is initialized in a common place (i.e.@Module ApplicationModule) -
Helpers
A set of classes, each of them with a very specific responsibility. Their function can range from talking to APIs or a database to implementing some specific business logic. The
DataSourcecombines and transforms the outputs from different helpers using Rx operators so it can:- Provide meaningful data to the Presenter,
- Group actions that will always happen together. This layer also contains the actual model classes that define how the data structure is.
-
Note: in a MVP context, the term "view" is overloaded:
- The class android.view.View will be referred to as "Android View"
- The view that receives commands from a presenter in MVP, will be simply called "view".
Implementation
Feature components
There are multiple ways to create the relevant parts of a feature using the Data Binding Library. In this case, the responsibility of each component in this sample is:
- Activity/Fragment: handles views, interaction with framework components (options menu, Snackbar, FAB, Adapter for list…)
- Presenter: receives user actions and retrieves the data from the repository. If it doesn't do data loading, it's calling an action handler.
- ViewModel: Exposes data for a particular view
Some features don't have a ViewMode as they use the model directly.
Dependencies
- Common Android support libraries (
com.android.support.*) - Dagger2
- Retrofit2
- RxJava and RxAndroid
- The Data Binding Framework
- Android Testing Support Library (Espresso, AndroidJUnitRunner…)
- Mockito
Features
Complexity - understandability
Use of architectural frameworks/libraries/tools:
See Dependencies part above
Conceptual complexity
Not estimate
Testability
Unit testing
High, presenters are unit tested as well as repositories and data sources.
UI testing
High, injection of fake modules allows for testing with fake data
Code metrics
High class and methods amount
Maintainability
Ease of amending or adding a feature
High.
Learning cost
- The Data Binding library takes care of the communication between some components, so developers need to understand what it does and doesn't before making changes to the code.
- Developers need to be aware of how Dagger2 works, although the setup of new features should look very similar to existing ones.
- Developers need to have knowledge in
RxJavaandRxAndroid.