Skip to content
This repository was archived by the owner on Apr 19, 2022. It is now read-only.

Commit 55294d7

Browse files
committed
Removed AutoValue, updated README, no more java
1 parent 5ac4d3f commit 55294d7

File tree

5 files changed

+138
-149
lines changed

5 files changed

+138
-149
lines changed

README.md

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,49 @@
1-
# TODO-MVI-RxJava
1+
# TODO-MVI-RxJava-Kotlin
2+
3+
### Java Version
4+
5+
You can fin the Java version of this app [here](https://github.com/oldergod/android-architecture/tree/todo-mvi-rxjava).
26

37
### Contributors
48

5-
[Benoît Quenaudon](https://github.com/oldergod) and [David González](https://github.com/malmstein).
9+
[Benoît Quenaudon](https://github.com/oldergod)
610

711
### Summary
812

9-
This version of the app is called TODO-MVI-RxJava. It is based on an Android ported version of the Model-View-Intent architecture and uses RxJava to implement the reactive caracteristic of the architecture. It is initially a fork of the [TODO-MVP-RXJAVA](https://github.com/googlesamples/android-architecture/tree/todo-mvp-rxjava).
13+
This version of the app is called TODO-MVI-RxJava-Kotlin. It is based on an Android ported version of the Model-View-Intent architecture and uses RxJava to implement the reactive caracteristic of the architecture. It is initially a fork of the [TODO-MVP-RXJAVA](https://github.com/googlesamples/android-architecture/tree/todo-mvp-rxjava).
1014

1115
The MVI architecture embraces reactive and functional programming. The two main components of this architecture, the _View_ and the _ViewModel_ can be seen as functions, taking an input and emiting outputs to each other. The _View_ takes input from the _ViewModel_ and emit back _intents_. The _ViewModel_ takes input from the _View_ and emit back _view states_. This means the _View_ has only one entry point to forward data to the _ViewModel_ and vice-versa, the _ViewModel_ only has one way to pass information to the _View_.
1216
This is reflected in their API. For instance, The _View_ has only two exposed methods:
1317

14-
```java
15-
public interface MviView {
16-
Observable<MviIntent> intents();
18+
```kotlin
19+
interface MviView {
20+
fun intents(): Observable<MviIntent>
1721

18-
void render(MviViewState state);
22+
fun render(state: MviViewState)
1923
}
2024
```
2125

2226
A _View_ will a) emit its intents to a _ViewModel_, and b) subscribes to this _ViewModel_ in order to receive _states_ needed to render its own UI.
2327

2428
A _ViewModel_ exposes only two methods as well:
2529

26-
```java
27-
public interface MviViewModel {
28-
void processIntents(Observable<MviIntent> intents);
30+
```kotlin
31+
interface MviViewModel {
32+
fun processIntents(intents: Observable<MviIntent>)
2933

30-
Observable<MviViewState> states();
34+
fun states(): Observable<MviViewState>
3135
}
3236
```
3337

3438
A _ViewModel_ will a) process the _intents_ of the _View_, and b) emit a _view state_ back so the _View_ can reflect the change, if any.
3539

36-
<img src="https://raw.githubusercontent.com/oldergod/android-architecture/todo-mvi-rxjava/art/MVI_global.png" alt="View and ViewModel are simple functions."/>
40+
<img src="https://raw.githubusercontent.com/oldergod/android-architecture/todo-mvi-rxjava-kotlin/art/MVI_global.png" alt="View and ViewModel are simple functions."/>
3741

3842
### The User is a function
3943

4044
The MVI architecture sees the user as part of the data flow, a functionnal component taking input from the previous one and emitting event to the next. The user receives an input―the screen from the application―and ouputs back events (touch, click, scroll...). On Android, the input/output of the UI is at the same place; either physically as everything goes through the screen or in the program: I/O inside the activity or the fragment. Including the User to seperate the input of the view from its output helps keeping the code healty.
4145

42-
<img src="https://raw.githubusercontent.com/oldergod/android-architecture/todo-mvi-rxjava/art/MVI_detail.png" alt="Model-View-Intent architecture in details"/>
46+
<img src="https://raw.githubusercontent.com/oldergod/android-architecture/todo-mvi-rxjava-kotlin/art/MVI_detail.png" alt="Model-View-Intent architecture in details"/>
4347

4448
### MVI in details
4549

@@ -80,19 +84,18 @@ The _State_ contains all the information the _View_ needs to render itself.
8084

8185
The `TasksDataSource` interface contains methods like:
8286

83-
```java
84-
Single<List<Task>> getTasks();
87+
```kotlin
88+
fun getTasks(): Single<List<Task>>
8589

86-
Single<Task> getTask(@NonNull String taskId);
90+
fun getTask(taskId: String): Single<Task>
8791

88-
Completable completeTask(@NonNull Task task);
92+
fun completeTask(task: Task): Completable
8993
```
9094

9195
This is implemented in `TasksLocalDataSource` with the help of [SqlBrite](https://github.com/square/sqlbrite). The result of queries to the database being easily exposed as streams of data.
9296

93-
```java
94-
@Override
95-
public Single<List<Task>> getTasks() {
97+
```kotlin
98+
override fun getTasks(): Single<List<Task>> {
9699
...
97100
return databaseHelper.createQuery(TaskEntry.TABLE_NAME, sql)
98101
.mapToList(taskMapperFunction)
@@ -106,7 +109,7 @@ Handling of the working threads is done with the help of RxJava's `Scheduler`s.
106109

107110
### Immutability
108111

109-
Data immutability is embraced to help keeping the logic simple. Immutability means that we do not need to manage data being mutated in other methods, in other threads, etc; because we are sure the data cannot change. Data immutability is implemented with the help of [AutoValue](https://github.com/google/auto/tree/master/value). Our all value objects are interfaces of which AutoValue will generate the implementation.
112+
Data immutability is embraced to help keeping the logic simple. Immutability means that we do not need to manage data being mutated in other methods, in other threads, etc; because we are sure the data cannot change. Data immutability is implemented with Kotlin's `data class`.
110113

111114
### Functional Programming
112115

@@ -122,7 +125,6 @@ We use the [Architecture Components library](https://developer.android.com/topic
122125
* [RxJava2](https://github.com/ReactiveX/RxJava)
123126
* [RxAndroid](https://github.com/ReactiveX/RxAndroid)
124127
* [SqlBrite](https://github.com/square/sqlbrite)
125-
* [AutoValue](https://github.com/google/auto/tree/master/value)
126128
* [Architecture Components](https://developer.android.com/topic/libraries/architecture/index.html)
127129
* [RxBinding](https://github.com/JakeWharton/RxBinding)
128130

@@ -156,10 +158,10 @@ Compared to TODO-MVP, new classes were added for 1) setting the interfaces to he
156158
-------------------------------------------------------------------------------
157159
Language files blank comment code
158160
-------------------------------------------------------------------------------
159-
Java 73 1275 1689 4798 (3639 in MVP-RXJAVA)
161+
Kotlin 75 890 1659 3990 (3639 in MVP-RXJAVA, (4798 in MVI-RXJAVA-KOTLIN))
160162
XML 34 97 338 610
161163
-------------------------------------------------------------------------------
162-
SUM: 107 1372 2027 5408
164+
SUM: 109 987 1997 4600
163165
-------------------------------------------------------------------------------
164166
```
165167
### Maintainability

app/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ dependencies {
9191
implementation "android.arch.lifecycle:extensions:$rootProject.archComponentsVersion"
9292
implementation "io.reactivex.rxjava2:rxkotlin:$rootProject.rxKotlinVersion"
9393
kapt "android.arch.lifecycle:compiler:$rootProject.archComponentsVersion"
94-
annotationProcessor "com.google.auto.value:auto-value:$rootProject.autoValueVersion"
95-
api "com.google.auto.value:auto-value:$rootProject.autoValueVersion"
9694

9795
// Dependencies for local unit tests
9896
testImplementation "com.nhaarman:mockito-kotlin:$rootProject.mockitoKotlinVersion"

app/src/androidTest/java/com/example/android/architecture/blueprints/todoapp/custom/action/NavigationViewActions.java

Lines changed: 0 additions & 122 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright 2016, The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.android.architecture.blueprints.todoapp.custom.action
18+
19+
import android.content.res.Resources.NotFoundException
20+
import android.support.design.widget.NavigationView
21+
import android.support.test.espresso.PerformException
22+
import android.support.test.espresso.UiController
23+
import android.support.test.espresso.ViewAction
24+
import android.support.test.espresso.matcher.ViewMatchers
25+
import android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom
26+
import android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast
27+
import android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
28+
import android.support.test.espresso.util.HumanReadables
29+
import android.support.v4.widget.DrawerLayout
30+
import android.view.Menu
31+
import android.view.View
32+
import org.hamcrest.Matcher
33+
import org.hamcrest.Matchers.allOf
34+
35+
/**
36+
* View actions for interacting with [NavigationView]
37+
*/
38+
object NavigationViewActions {
39+
/**
40+
* Returns a [ViewAction] that navigates to a menu item in [NavigationView] using a
41+
* menu item resource id.
42+
*
43+
*
44+
*
45+
*
46+
* View constraints:
47+
*
48+
* * View must be a child of a [DrawerLayout]
49+
* * View must be of type [NavigationView]
50+
* * View must be visible on screen
51+
* * View must be displayed on screen
52+
*
53+
*
54+
* @param menuItemId the resource id of the menu item
55+
* @return a [ViewAction] that navigates on a menu item
56+
*/
57+
fun navigateTo(menuItemId: Int): ViewAction {
58+
return object : ViewAction {
59+
override fun perform(uiController: UiController, view: View) {
60+
val navigationView = view as NavigationView
61+
val menu = navigationView.menu
62+
if (null == menu.findItem(menuItemId)) {
63+
throw PerformException.Builder()
64+
.withActionDescription(this.description)
65+
.withViewDescription(HumanReadables.describe(view))
66+
.withCause(RuntimeException(getErrorMessage(menu, view)))
67+
.build()
68+
}
69+
menu.performIdentifierAction(menuItemId, 0)
70+
uiController.loopMainThreadUntilIdle()
71+
}
72+
73+
private fun getErrorMessage(menu: Menu, view: View): String {
74+
val NEW_LINE = System.getProperty("line.separator")
75+
val errorMessage = StringBuilder("Menu item was not found, " + "available menu items:")
76+
.append(NEW_LINE)
77+
for (position in 0 until menu.size()) {
78+
errorMessage.append("[MenuItem] position=").append(position)
79+
val menuItem = menu.getItem(position)
80+
if (menuItem != null) {
81+
val itemTitle = menuItem.title
82+
if (itemTitle != null) {
83+
errorMessage.append(", title=").append(itemTitle)
84+
}
85+
if (view.resources != null) {
86+
val itemId = menuItem.itemId
87+
try {
88+
errorMessage.append(", id=")
89+
val menuItemResourceName = view.resources.getResourceName(itemId)
90+
errorMessage.append(menuItemResourceName)
91+
} catch (nfe: NotFoundException) {
92+
errorMessage.append("not found")
93+
}
94+
95+
}
96+
errorMessage.append(NEW_LINE)
97+
}
98+
}
99+
return errorMessage.toString()
100+
}
101+
102+
override fun getDescription(): String {
103+
return "click on menu item with id"
104+
}
105+
106+
override fun getConstraints(): Matcher<View> {
107+
return allOf(isAssignableFrom(NavigationView::class.java),
108+
withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE), isDisplayingAtLeast(90))
109+
}
110+
}
111+
}
112+
}

build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ ext {
4545
rxandroidVersion = '2.0.1'
4646
sqlbriteVersion = '2.0.0'
4747
jsr305Version = '3.0.1'
48-
autoValueVersion = '1.3'
4948
rxBindingVersion = '2.0.0'
5049
archComponentsVersion = '1.0.0'
5150
mockitoKotlinVersion = '1.5.0'

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy