# mv<sup>2</sup>m
Android MVVM lightweight library based on Android Data Binding
[![Circle CI](https://circleci.com/gh/fabioCollini/mv2m/tree/master.svg?style=svg)](https://circleci.com/gh/fabioCollini/mv2m/tree/master)
![JitPack](https://img.shields.io/github/tag/fabioCollini/mv2m.svg?label=JitPack)
[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-mv2m-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/2524)
The goal of mv<sup>2</sup>m is to simplify JVM testing of an Android application.
The [demo module](/demo) contains a simple example of usage of mv<sup>2</sup>m library.
The [official app](https://github.com/commit-non-javisti/CoseNonJavisteAndroidApp) of the Italian blog [cosenonjaviste.it](http://cosenonjaviste.it)
is a more complex example (built using Dagger and RxJava). This [repository](https://github.com/fabioCollini/android-testing/tree/final)
contains the mv<sup>2</sup>m porting of [android-testing codelab](https://github.com/googlecodelabs/android-testing) repository.
Mv2m is available on [JitPack](https://jitpack.io/#fabioCollini/mv2m/),
add the JitPack repository in your build.gradle (in top level dir):
```gradle
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
```
and the dependency in the build.gradle of the module:
```gradle
dependencies {
//core module
compile 'com.github.fabioCollini.mv2m:mv2m:0.4.1'
//RxJava support
compile 'com.github.fabioCollini.mv2m:mv2mrx:0.4.1'
//RecyclerView support
compile 'com.github.fabioCollini.mv2m:mv2mrecycler:0.4.1'
}
```
## Components of mv<sup>2</sup>m
##### Model
A Model class contains the data used to populate the user interface using Data Binding library. It's saved automatically in Actvity/Fragment state, for this reason it must implement Parcelable interface.
##### View
The View is an Activity or a Fragment, the user interface is managed using Android Data Binding. You need to extend ViewModelActivity
or ViewModelFragment class and implement createViewModel method returning a new ViewModel object.
##### ViewModel
The ViewModel is a subclass of ViewModel class, it is automatically saved in a retained fragment to
avoid the creation of a new object on every configuration change.
The ViewModel is usually the object bound to the layout using the Data Binding framework.
It manages the background tasks and all the business logic of the application.
![mv2m class diagram](/mv2m-class-diagram.png)
## JUnit tests
The ViewModel is not connected to the View, for this reason it's easily testable using a JVM test.
The demo module contains
[some](https://github.com/fabioCollini/mv2m/blob/master/demo/src/test/java/it/cosenonjaviste/demomv2m/core/detail/NoteViewModelTest.java)
[JUnit tests](https://github.com/fabioCollini/mv2m/blob/master/demo/src/test/java/it/cosenonjaviste/demomv2m/core/list/NoteListViewModelTest.java)
for ViewModel classes.
## Activity
Sometimes an Activity object is required to perform some operations, for example you need an Activity
object to show a SnackBar message or to start another Activity. In this case you can create a new class with
some methods with an ActivityHolder parameter:
```java
public class SnackbarMessageManager {
@Override public void showMessage(ActivityHolder activityHolder, int message) {
if (activityHolder != null) {
Snackbar.make(activityHolder.getActivity().findViewById(android.R.id.content), message, Snackbar.LENGTH_LONG).show();
}
}
}
```
An implementation of this class can be referenced from a ViewModel object. ViewModel class contains
a protected ActivityHolder field containing a reference to the current Activity that can be used as parameter
(it's automatically updated every configuration change).
In this way it's easy to show a SnackBar from a ViewModel.
In a JVM test SnackbarMessageManager object can be mocked to avoid dependencies on Android framework.
## ViewModel argument
ViewModel class has two generic parameters: the type of the argument and the type of the Model class.
The argument can be used when the ViewModel needs an argument, for example in a detail ViewModel the argument
is the id of the object you have to show. The argument must be an object that can be written in a Bundle
(a primitive type, a Serializable or a Parcelable).
Using an ActivityHolder object you can start a new Activity passing an argument:
```java
activityHolder.startActivity(NoteActivity.class, noteId);
```
ViewModel class contains a protected field argument that can be used to load the model data based on the argument.
In case you use Fragments as View objects you can use ArgumentManager.instantiateFragment method to
create a new Fragment and set the argument on it.
## Work in progress
This library (and the Android Data Binding library) is still a beta version; feedbacks, bug reports and pull requests are welcome!
## Talk is cheap. Show me the code.
Let's see how to use mv<sup>2</sup>m to implement a simple example: a currency converter Activity.
![mv2m demo](/demo-mv2m.png)
The Model class contains two fields, one is bound with the input EditText and the other with the output TextField:
```java
public class CurrencyConverterModel implements Parcelable {
public ObservableString input = new ObservableString();
public ObservableString output = new ObservableString();
//Parcelable implementation...
}
```
Using RateLoader class it's possible to load a rate from an external source (for example a REST service), in
this first implementation it executes everything synchronously:
```java
public class RateLoader {
private static RateLoader INSTANCE = new RateLoader();
private RateLoader() {
}
public static RateLoader instance() {
return INSTANCE;
}
public float loadRate() {
//...
}
}
```
All the business logic is in the CurrencyConverterViewModel class, it extends ViewModel class defining
two generic parameters: Void (we don't need any argument) and the Model class.
```java
public class CurrencyConverterViewModel extends ViewModel<Void, CurrencyConverterModel> {
private RateLoader rateLoader;
public CurrencyConverterViewModel(RateLoader rateLoader) {
this.rateLoader = rateLoader;
}
@NonNull @Override public CurrencyConverterModel createModel() {
return new CurrencyConverterModel();
}
public void calculate() {
String inputString = model.input.get();
float input = Float.parseFloat(inputString);
model.output.set(new DecimalFormat("0.00").format(input * rateLoader.loadRate()));
}
}
```
We use the dependency injection on the constructor to manage a reference to a RateLoader object.
The createModel method is overridden to create and return a new Model object.
The ViewModel class has no Android dependencies, it can be tested easily using a JUnit test:
```java
@RunWith(MockitoJUnitRunner.class)
public class CurrencyConverterViewModelTest {
@Mock RateLoader rateLoader;
@InjectMocks CurrencyConverterViewModel viewModel;
@Test
public void testConvertCurrency() {
when(rateLoader.loadRate()).thenReturn(2f);
CurrencyConverterModel model = viewModel.initAndResume();
model.input.set("123");
viewModel.calculate();
assertThat(model.output.get()).isEqualTo("246.00");
}
}
```
In this JUnit test we use Mockito to create a mock of RateLoader object, in this way the test is
repeatable because it's not dependent on external sources.
Data binding library is used to bind ViewModel object to the layout:
```xml
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="viewModel"
type="it.cosenonjaviste.demomv2m.core.currencyconverter1.CurrencyConverterViewModel"/>
</data>
<LinearLayout
android:layout_width="match_parent"
没有合适的资源?快使用搜索试试~ 我知道了~
mvvm-设计模式框架.zip
共123个文件
java:73个
xml:14个
png:11个
3星 · 超过75%的资源 需积分: 14 14 下载量 195 浏览量
2016-02-24
15:02:40
上传
评论
收藏 274KB ZIP 举报
温馨提示
mvvm-设计模式框架,Android MVVM framework write in kotlin, develop Android has never been so fun.
资源推荐
资源详情
资源评论
收起资源包目录
mvvm-设计模式框架.zip (123个子文件)
gradlew.bat 2KB
.gitignore 57B
.gitignore 13B
.gitignore 7B
.gitignore 7B
.gitignore 7B
build.gradle 6KB
build.gradle 816B
build.gradle 678B
build.gradle 672B
build.gradle 590B
settings.gradle 53B
gradlew 5KB
gradle-wrapper.jar 49KB
ParcelableTester.java 8KB
NoteViewModelTest.java 6KB
RxHolder.java 6KB
NoteViewModel.java 5KB
NoteListViewModelTest.java 5KB
ArgumentManager.java 5KB
BindableAdapter.java 4KB
ViewModelManager.java 4KB
ObjectFactory.java 4KB
NoteListViewModel.java 3KB
NoteActivityTest.java 3KB
NoteModel.java 3KB
RecyclerViewDemoActivity.java 3KB
CurrencyConverterViewModel.java 3KB
CurrencyConverterViewModel.java 3KB
ActivityHolder.java 3KB
NoteListModel.java 3KB
ViewModelActivity.java 3KB
CurrencyConverterViewModelTest.java 2KB
NoteListActivity.java 2KB
NoteListActivityTest.java 2KB
ViewModelFragment.java 2KB
ViewModel.java 2KB
CurrencyConverterViewModelTest.java 2KB
BindableViewHolder.java 2KB
JsonTest.java 2KB
CurrencyConverterActivityTest.java 2KB
WeakOnListChangedCallback.java 2KB
CurrencyConverterViewModelTest.java 2KB
TestData.java 2KB
Note.java 2KB
CurrencyConverterViewModel.java 2KB
CurrencyConverterModel.java 2KB
CurrencyConverterModel.java 2KB
CurrencyConverterModel.java 2KB
CurrencyConverterModel.java 2KB
AdapterOnListChangedCallback.java 2KB
NoteActivity.java 2KB
ViewModelRetainedFragment.java 2KB
RxViewModel.java 2KB
SimpleBindableViewHolder.java 2KB
CurrencyConverterActivity.java 2KB
CurrencyConverterViewModel.java 1KB
CurrencyConverterViewModelTest.java 1KB
ViewModelActivityTestRule.java 1KB
ActivityResult.java 1KB
NoteViewHolder.java 1KB
BaseBindableViewHolder.java 1KB
RateLoader.java 1KB
SnackbarMessageManager.java 1KB
DataBindingConverters.java 1KB
SchedulerManager.java 1KB
NoteListModelTest.java 1KB
AndroidSchedulerManager.java 1KB
ActivityNavigator.java 1KB
RateLoader.java 1015B
NoteModelTest.java 999B
NoteSaver.java 978B
ViewModelContainer.java 965B
NoteListResponse.java 960B
RateLoader.java 912B
NoteTest.java 911B
SaveResponse.java 881B
NoteLoader.java 856B
DemoItem.java 827B
Navigator.java 816B
TestExecutor.java 815B
RateLoader.java 806B
MessageManager.java 792B
NormalDemoItem.java 767B
TitleDemoItem.java 765B
TestObjectFactory.java 636B
TestUtils.java 244B
LICENSE 11KB
README.md 18KB
mv2m-class-diagram.png 51KB
demo-mv2m.png 22KB
ic_launcher.png 14KB
ic_launcher.png 9KB
ic_launcher.png 6KB
ic_launcher.png 4KB
ic_launcher.png 2KB
ic_plus.png 252B
ic_plus.png 189B
ic_plus.png 167B
ic_plus.png 129B
共 123 条
- 1
- 2
资源评论
- Cideason2016-04-12可以 參考看看。
Lucky丨斌
- 粉丝: 2
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 细胞的奇迹:吃出来的免疫力(美亚畅销书!作者的TED演讲播放量超300万次!《谷物大脑》作者、《三联生活周刊》推荐!吃下对的食物,改善你的... (Z-Library).azw3
- 智能手机产品拆解,使用mindmaster打开
- 11111111111111
- 统信系统ARM64依赖openssl-1.0.2版本的libssl.so.10和libcrypto.so.10文件
- 奥比中光python sdk
- 冯超楠17.py
- OCR识别-基于视觉注意力机制Attention实现的OCR识别算法-附项目源码-优质项目实战.zip
- Java 使用蒙特卡洛方法估算PI的近似值(源代码)
- main.cpp
- 电子木鱼小程序源码电子木鱼小程序源码
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功