Skip to content

Commit 94adceb

Browse files
committed
Adds READMEs for databinding and mvp-loaders
1 parent 0ec6db8 commit 94adceb

File tree

2 files changed

+296
-0
lines changed

2 files changed

+296
-0
lines changed

todo-databinding/README.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# TODO-DataBinding
2+
3+
It is based on the [todo-mvp](https://github.com/googlesamples/android-architecture/tree/master/todo-mvp) sample and uses the Data Binding library (currently in beta) to display data
4+
and bind UI elements to actions.
5+
6+
It's doesn't follow a strict Model-View-ViewModel or a Model-View-Presenter
7+
pattern, as it uses both View Models and Presenters.
8+
9+
The [Data Binding Library](http://developer.android.com/tools/data-binding/guide.html#data_objects) saves on boilerplate code allowing UI elements to be bound to a property in a
10+
data model.
11+
12+
* Layout files are used to bind data to UI elements
13+
* Events are also bound with an action handler
14+
* Data can be observed and set up to be updated automatically when needed
15+
16+
<img src="https://github.com/googlesamples/android-architecture/wiki/images/mvp-databinding.png" alt="Diagram"/>
17+
18+
### Data binding
19+
20+
In the todo-mvp sample, a Task description is set in the [TaskDetailFragment](https://github.com/googlesamples/android-architecture/blob/master/todo-mvp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailFragment.java):
21+
22+
23+
```
24+
public void onCreateView(...) {
25+
...
26+
mDetailDescription = (TextView)
27+
root.findViewById(R.id.task_detail_description);
28+
}
29+
30+
@Override
31+
public void showDescription(String description) {
32+
mDetailDescription.setVisibility(View.VISIBLE);
33+
mDetailDescription.setText(description);
34+
}
35+
```
36+
In this sample, the [TaskDetailFragment](https://github.com/googlesamples/android-architecture/blob/master/todo-databinding/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailFragment.java) simply passes the Task to the data binding:
37+
38+
39+
```
40+
@Override
41+
public void showTask(Task task) {
42+
mViewDataBinding.setTask(task);
43+
}
44+
```
45+
and the library will take care of displaying it, as defined by the layout (<code>[taskdetail\_frag.xml](https://github.com/googlesamples/android-architecture/blob/master/todo-databinding/app/src/main/res/layout/taskdetail_frag.xml)</code>)
46+
47+
48+
```
49+
&lt;TextView
50+
android:id="@+id/task_detail_description"
51+
...
52+
android:text="@{task.description}" />
53+
54+
```
55+
### Event binding
56+
57+
Data binding eliminates the need to call <code>findViewById() </code>and event binding can also help minimizing <code>setOnClickListener()</code>.
58+
59+
In this CheckBox from <code>[taskdetail\_frag.xml](https://github.com/googlesamples/android-architecture/blob/master/todo-databinding/app/src/main/res/layout/taskdetail_frag.xml)</code>, the presenter is called directly when the user taps on it:
60+
61+
62+
```
63+
&lt;CheckBox
64+
android:id="@+id/task_detail_complete"
65+
...
66+
android:checked="@{task.completed}"
67+
android:onCheckedChanged="@{(cb, isChecked) ->
68+
presenter.completeChanged(task, isChecked)}" />
69+
```
70+
### Observing data
71+
72+
The view that shows the list of tasks (TasksFragment) only needs to know if the
73+
list is empty to show the appropriate message in that case. It uses [TasksViewModel](https://github.com/googlesamples/android-architecture/blob/master/todo-databinding/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.java) to provide that information to the layout. When the list size is set, only the
74+
relevant properties are notified and the UI elements bound to those properties
75+
are updated.
76+
77+
78+
```
79+
public void setTaskListSize(int taskListSize) {
80+
mTaskListSize = taskListSize;
81+
notifyPropertyChanged(BR.noTaskIconRes);
82+
notifyPropertyChanged(BR.noTasksLabel);
83+
notifyPropertyChanged(BR.currentFilteringLabel);
84+
notifyPropertyChanged(BR.notEmpty);
85+
notifyPropertyChanged(BR.tasksAddViewVisible);
86+
}
87+
```
88+
## Feature components
89+
90+
There are multiple ways to create the relevant parts of a feature using the
91+
Data Binding Library. In this case, the responsibility of each component in
92+
this sample is:
93+
94+
* Activity: object creation
95+
* Fragment: interaction with framework components (options menu, Snackbar, FAB,
96+
Adapter for list…)
97+
* Presenter: receives user actions and retrieves the data from the repository. If
98+
it doesn't do data loading, it's calling an action handler (See [TasksItemActionHandler](https://github.com/googlesamples/android-architecture/blob/master/todo-databinding/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksItemActionHandler.java))
99+
* ViewModel: Exposes data for a particular view
100+
101+
Some features don't have a ViewModel ([TaskDetail](https://github.com/googlesamples/android-architecture/tree/master/todo-databinding/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail), [AddEditTask](https://github.com/googlesamples/android-architecture/tree/master/todo-databinding/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask)) as they use the Task model directly.
102+
103+
## Additional dependencies
104+
105+
Data Binding Library.
106+
107+
## Features
108+
109+
### Testability
110+
111+
#### Unit testing
112+
113+
As the Data Binding Library takes care of many of the wiring that would usually
114+
be unit tested, the number of unit tests is lower although the test coverage
115+
should be similar.
116+
117+
#### UI testing
118+
119+
No difference with MVP.
120+
121+
### Code metrics
122+
123+
Compared to MVP, there are more Java classes but less code per class. Because
124+
some wiring is moved to layouts, there are more XML lines.
125+
126+
127+
```
128+
-------------------------------------------------------------------------------
129+
Language files blank comment code
130+
-------------------------------------------------------------------------------
131+
Java 50 1079 1552 3327 (3450 in MVP)
132+
XML 34 122 337 714
133+
-------------------------------------------------------------------------------
134+
SUM: 84 1201 1889 4041
135+
-------------------------------------------------------------------------------
136+
```
137+
### Maintainability
138+
139+
#### Ease of amending or adding a feature
140+
141+
Easier than MVP for small changes. A new feature might require some experience
142+
with the library.
143+
144+
#### Learning cost
145+
146+
The Data Binding library takes care of the communication between some
147+
components, so developers need to understand what it does and doesn't before
148+
making changes to the code.
149+

todo-mvp-loaders/README.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# TODO-MVP-Loaders
2+
3+
It is based on the [TODO-MVP](https://github.com/googlesamples/android-architecture/tree/master/todo-mvp) sample and uses Loaders to get the data from the tasks repository.
4+
5+
<img src="https://github.com/googlesamples/android-architecture/wiki/images/mvp-loaders.png" alt="Diagram"/>
6+
7+
The advantages of Loaders, from the [Loaders documentation page](http://developer.android.com/guide/components/loaders.html), are:
8+
9+
* They provide asynchronous loading of data, removing the need for callbacks in
10+
the repository.
11+
* They monitor the source of their data and deliver new results when the content
12+
changes, in our case, the repository.
13+
* They automatically reconnect to the last loader when being recreated after a
14+
configuration change.
15+
16+
## Code
17+
18+
### Asynchronous loading
19+
20+
The Loaders ([TaskLoader](https://github.com/googlesamples/android-architecture/blob/master/todo-mvp-loaders/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/source/TaskLoader.java) and [TasksLoader](https://github.com/googlesamples/android-architecture/blob/master/todo-mvp-loaders/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/source/TasksLoader.java)) are responsible for fetching the data and extend AsyncTaskLoader.
21+
22+
In [src/data/source/TasksLoader.java](https://github.com/googlesamples/android-architecture/blob/master/todo-mvp-loaders/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/source/TasksLoader.java):
23+
24+
25+
```
26+
@Override
27+
public List&lt;Task> loadInBackground() {
28+
return mRepository.getTasks();
29+
}
30+
```
31+
The results are received in the UI Thread, handled by the presenter.
32+
33+
In [TasksPresenter.java](https://github.com/googlesamples/android-architecture/blob/master/todo-mvp-loaders/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksPresenter.java)
34+
35+
36+
```
37+
@Override
38+
public void onLoadFinished(Loader&lt;List&lt;Task>> loader, List&lt;Task>
39+
data) {
40+
mTasksView.setLoadingIndicator(false);
41+
42+
mCurrentTasks = data;
43+
if (mCurrentTasks == null) {
44+
mTasksView.showLoadingTasksError();
45+
} else {
46+
showFilteredTasks();
47+
}
48+
}
49+
```
50+
The presenter also triggers the loading the data, like in the MVP sample but in
51+
this case it does it through the LoaderManager:
52+
53+
54+
```
55+
@Override
56+
public void start() {
57+
mLoaderManager.initLoader(TASKS_QUERY, null, this);
58+
}
59+
```
60+
### Content observer
61+
62+
After every content change in the repository, <code>notifyContentObserver()</code> is called.
63+
64+
In [src/data/source/TasksRepository.java](https://github.com/googlesamples/android-architecture/blob/master/todo-mvp-loaders/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/source/TasksRepository.java):
65+
66+
67+
```
68+
@Override
69+
public void deleteTask(@NonNull String taskId) {
70+
mTasksRemoteDataSource.deleteTask(checkNotNull(taskId));
71+
mTasksLocalDataSource.deleteTask(checkNotNull(taskId));
72+
73+
mCachedTasks.remove(taskId);
74+
75+
// Update the UI
76+
notifyContentObserver();
77+
}
78+
```
79+
This notifies the Loader which in this case simply forces a reload of data.
80+
81+
In [TasksLoader.java](https://github.com/googlesamples/android-architecture/blob/master/todo-mvp-loaders/app/src/main/java/com/example/android/architecture/blueprints/todoapp/data/source/TasksLoader.java):
82+
83+
84+
```
85+
@Override
86+
public void onTasksChanged() {
87+
if (isStarted()) {
88+
forceLoad();
89+
}
90+
}
91+
```
92+
## Additional dependencies
93+
94+
This project uses the Loaders framework available from Android 3.0 (API Level
95+
11).
96+
97+
## Features
98+
99+
### Complexity - understandability
100+
101+
#### Use of architectural frameworks/libraries/tools:
102+
103+
No external frameworks.
104+
105+
#### Conceptual complexity
106+
107+
Developers need to be familiar with the Loaders framework, which is not
108+
trivial.
109+
110+
### Testability
111+
112+
#### Unit testing
113+
114+
The use of the Loaders framework adds a big dependency with the Android
115+
framework so unit testing is harder.
116+
117+
#### UI testing
118+
119+
No difference with MVP.
120+
121+
### Code metrics
122+
123+
Compared to MVP, the only new classes are TaskLoader and TasksLoader. Parts of
124+
the code are simpler as Loaders take care of the asynchronous work.
125+
126+
127+
```
128+
-------------------------------------------------------------------------------
129+
Language files blank comment code
130+
-------------------------------------------------------------------------------
131+
Java 48 1085 1444 3517 (3450 in MVP)
132+
XML 34 97 337 601
133+
-------------------------------------------------------------------------------
134+
SUM: 82 1182 1781 4118
135+
-------------------------------------------------------------------------------
136+
137+
```
138+
### Maintainability
139+
140+
#### Ease of amending or adding a feature
141+
142+
Similar to MVP
143+
144+
#### Learning cost
145+
146+
Medium as the Loaders framework is not trivial.
147+

0 commit comments

Comments
 (0)