Android MVVM library, module mvvm-api

Android ViewModel with "clean architecture" and React states.

License

License

GroupId

GroupId

com.github.asuslennikov
ArtifactId

ArtifactId

mvvm-api
Last Version

Last Version

0.8.31
Release Date

Release Date

Type

Type

jar
Description

Description

Android MVVM library, module mvvm-api
Android ViewModel with "clean architecture" and React states.
Project URL

Project URL

https://github.com/asuslennikov/mvvm
Source Code Management

Source Code Management

https://github.com/asuslennikov/mvvm

Download mvvm-api

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.asuslennikov/mvvm-api/ -->
<dependency>
    <groupId>com.github.asuslennikov</groupId>
    <artifactId>mvvm-api</artifactId>
    <version>0.8.31</version>
</dependency>
// https://jarcasting.com/artifacts/com.github.asuslennikov/mvvm-api/
implementation 'com.github.asuslennikov:mvvm-api:0.8.31'
// https://jarcasting.com/artifacts/com.github.asuslennikov/mvvm-api/
implementation ("com.github.asuslennikov:mvvm-api:0.8.31")
'com.github.asuslennikov:mvvm-api:jar:0.8.31'
<dependency org="com.github.asuslennikov" name="mvvm-api" rev="0.8.31">
  <artifact name="mvvm-api" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.github.asuslennikov', module='mvvm-api', version='0.8.31')
)
libraryDependencies += "com.github.asuslennikov" % "mvvm-api" % "0.8.31"
[com.github.asuslennikov/mvvm-api "0.8.31"]

Dependencies

compile (2)

Group / Artifact Type Version
io.reactivex.rxjava2 : rxjava jar 2.2.7
androidx.annotation » annotation jar 1.1.0

Project Modules

There are no modules declared in this project.

Android MVVM library

Build Status Download

It's small architectural library, inspired by Android ViewModel, ReactJS and Clean Architecture. It has not too many code and you easily can gasp the main idea of this projects just within 15-30 min.

Rationale

Application architecture with clear separation of concern shines most obviously on big projects or projects with constant changes. Should you use it for small projects or prototypes? I think, yes. At least, you definitely can get benefits in application stability, what is important for projects of any kind.

Pros:

  • You have clean and manageable components
  • It's easy to detect and isolate a failed part
  • With practice you will write code faster
  • It definitely boosts re-usability of your code
  • App becomes more open for changes
  • Writing tests is really easy task

Cons:

  • Even a small screen requires a pile of code for infrastructure (but it's not too big)
  • You need some time to get used to it
  • From now on you have no excuse for abandoning unit-tests

This project tries to reduce amount of infrastructure's code, which you need to write by yourself. It also enforces some limitations, which helps to follow SRP principle.

Usage

Artifacts are published in JCenter and Maven Central repository. Make sure that one of them is listed in the repository section of build.gradle file in your root project folder:

buildscript {
    repositories {
        jcenter()
    }
}

or

buildscript {
    repositories {
        mavenCentral()
    }
}
A single module project

If you have just a single module, then in build.gradle file of this module add these dependencies:

dependencies {
    implementation "com.github.asuslennikov:mvvm-domain:x.y.z"
    implementation "com.github.asuslennikov:mvvm-presentation:x.y.z"
}

Please replace the 'x.y.z' by the latest available version (check the JCenter badge at the top of file).

A multi-module project

if you follow the clean architecture guideline and have separate modules for your business rules (a domain module) and presentation (a presentation module), then:

  • in your domain module add this dependency in build.gradle file:
    dependencies {
        api "com.github.asuslennikov:mvvm-domain:x.y.z"
    }
  • and in presentation module:
    dependencies {
        implementation "com.github.asuslennikov:mvvm-presentation:x.y.z"
    }

Please replace the 'x.y.z' by the latest available version (check the JCenter badge at the top of file).

Library components

Data flow diagram

alt FullWidthImage

UML overview

On this image you can see an overview of main library components:

alt FullWidthImage

Components details

Presentation layer:

Screen
Name Screen
Synonyms View, Render
Component layer Presentation
Responsibility It renders a part of application UI (it controls what user see and how he can communicate with that part of UI).
UML diagram alt TableImage
Notes - It never changes State by itself, always delegates it to ViewModel.
- It doesn't have any behaviour-related logic. All this staff goes to ViewModel.
- It shouldn't have mutable local fields which have influence to UI (except, maybe, a saved State).
- Screen should have reference to only one ViewModel.
- Screen doesn't need any external dependencies, except the ViewModel (because it is the only one source of truth for the Screen).
- As a name for concrete class, you can use a general meaning plus the Screen suffix (for example LastNewsScreen). Layout file should have only general meaning as a name, without any suffix (don't use _fragment, _activity or _screen: last_news.xml)
- It is recommended to have Espresso tests for Screen. Unit tests are not necessary (because Screen have only UI logic and it's not easy to check correctness with regular unit tests).
Example link TBD
State
Name State
Synonyms ViewState, ScreenState, UIModel, Model
Component layer Presentation
Responsibility It describes a state (collection of elements' properties) at specific moment in time for part of UI
UML diagram alt TableImage
Notes - It's a POJO class (data class in Kotlin).
- It doesn't have any logic, only getters and setters.
- Successor of this interface should never implement the UseCaseInput or UseCaseOutput in the same time.
- As a name for implementation, it's recommended to use a name of specific screen and replace the Screen word by State (for example LastNewsState).
- Should implement some mechanism for serialization / deseralization. For example, use the @Parcel annotation or set JSON annotations of your favorite mapper.
- Fields have descriptive names, but not "action" names (use newsListLoaderVisible instead of showNewsListLoader).
- No need in Unit tests.
Example link TBD
Effect
Name Effect
Synonyms UIAction, Action
Component layer Presentation
Responsibility It represents some UI action, which should be executed only once (for example, open keyboard or launch shake animation for element).
UML diagram alt TableImage
Notes - It's useful for one-shot events, which can be skipped if user is not interacting with UI at given time (if application is in background)
Example link TBD
ViewModel
Name ViewModel
Synonyms Handler, Behaviour, Controller
Component layer Presentation
Responsibility It defines what to render on screen and how to process user input.
UML diagram alt TableImage
Notes - Methods should have names which represent a happened interaction, but not the expected result (use showMoreClicked(), but not the loadNextPage()).
- It can contain other ViewModels.
- You should remember, that when activity dies, the model dies as well. So keep in mind, that you should be able to restore inner ViewModel's fields based on given State object.
- All dependencies should be declared in constructor (don't use SomeClass.getInstance(), it makes component untestable).
- Component should have Unit tests.
Example link TBD

Domain layer:

UseCaseInput
Name UseCaseInput
Synonyms CommandArgument, Parameter
Component layer Domain
Responsibility It holds input information for UseCase
UML diagram alt TableImage
Notes - It's a POJO class (data class in Kotlin).
- It should be immutable.
- It doesn't have any logic, only getters.
- Successors of this interface shouldn't implement the State or UseCaseOutput interface at the same time.
Example link TBD
UseCaseOutput
Name UseCaseOutput
Synonyms CommandResult
Component layer Domain
Responsibility It holds UseCase result
UML diagram alt TableImage
Notes - It's a POJO class (data class in Kotlin).
- It should be immutable.
- It doesn't have any logic, only getters.
- Successors of this interface shouldn't implement the State or UseCaseInput interface at the same time.
Example link TBD
UseCase
Name UseCase
Synonyms BusinessScenario, Scenario, Interactor, Command
Component layer Domain
Responsibility It contains application's business logic
UML diagram alt TableImage
Notes - It has structure which is similar to algorithms: it has input data, result of work (output data) and rules by which it converts input to output.
- Implementation can reference to another UseCases.
- It communicates with data layer using interfaces (should be defined in domain layer) and takes concrete implementations as arguments in constructor.
- It has no connection with State in any way.
- It should have regular unit tests (since it has no platform specific logic).
Example link TBD

Data layer:

Manager
Name Manager
Synonyms Gateway, Repository
Component layer Data
Responsibility It provides a platform specific implementation for interfaces, defined in domain layer
UML diagram No specific component diagram
Notes - It doesn't know anything about presentation layer. It depends only on domain layer.
- It uses platform-specific tests (for example, you can use Robolectric).
Example link TBD

Additional reading:

Versions

Version
0.8.31
0.8.30
0.8.20