Skip to content

Commit c47e347

Browse files
committed
Update documentations and prepare to the next release
1 parent 25ac0a8 commit c47e347

File tree

3 files changed

+108
-46
lines changed

3 files changed

+108
-46
lines changed

README.md

Lines changed: 106 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
</p>
1111

1212
<p align="center">
13-
A lightweight Android thread-safe pipeline for communicating between lifecycle components with custom scopes.
13+
A lightweight Android lifecycle-aware and thread-safe pipeline for communicating between components with custom scopes.
1414
</p>
1515

16-
> <p align="center">Android components are essential building blocks of an Android application. <br>These independent components are very loosely coupled. The benefit is that they are really independently reusable,<br> but it makes to hard communicate with each other. </p>
16+
> <p align="center">Android components are essential building blocks of an Android application. <br>These independent components are very loosely coupled. The benefit is that they are really independently reusable, but it makes to hard communicate with each other. </p>
1717
1818
><p align="center"> The goal of this library is making easier to communicate and flow data with each other component like Activity, Fragment, Services, etc. And we can deliver data on each component easily and clear data on memory automatically following lifecycles. Also using custom scopes that are lifecycle aware makes developers can designate scoped data holder on their taste.</p>
1919
@@ -42,7 +42,7 @@ allprojects {
4242
And add a dependency code to your module's build.gradle file.
4343
```gradle
4444
dependencies {
45-
implementation "com.github.skydoves:chamber:1.0.2"
45+
implementation "com.github.skydoves:chamber:1.0.3"
4646
}
4747
```
4848

@@ -56,61 +56,60 @@ repositories {
5656
```
5757

5858
## Usage
59-
Chamber is scoped data holder with custom scopes that are lifecycle aware.
59+
Chamber is a lightweight lifecycle-aware pipeline based on scopes.
60+
6061
### ChamberScope
6162
The basic usage is creating a customized scope annotation using a `@ChamberScope` annotation. <br>
62-
`@ChamberScope` is used to build custom scopes that are lifecycle aware. Each scope is a temporal data holder that has `ChamberProperty` data and lifecycle stack. It should be annotated a class (activity, fragment, repository or any classes) that has `ChamberProperty` fields.
63+
`@ChamberScope` is used to build custom scopes that are lifecycle aware. Each scope will be used as a pipeline via `ChamberProperty` and it will be managed by the lifecycle stack. It should be annotated on classes (activity, fragment, repository, or any classes) that has `ChamberProperty` fields.
64+
6365
```kotlin
6466
@ChamberScope
6567
@Retention(AnnotationRetention.RUNTIME)
6668
annotation class UserScope
6769
```
6870

6971
### ChamberProperty
70-
ChamberProperty is an interactive class to the internal Chamber data holder and a lifecycleObserver <br>that can be observable.
71-
It should be used with `@ShareProperty` annotation that has a key name. If we want to use the same synchronized value on the same custom scope and different classes, we should use the same key.
72+
ChamberProperty is an interactive class to the internal Chamber data holder and a lifecycleObserver that can be observable.
73+
It should be used with `@ShareProperty` annotation that has a key name. If we want to use the same synchronized value on the same custom scope in different classes, we should use the same key.
7274

7375
```kotlin
74-
@ShareProperty("name") // name is a key name.
75-
var username = ChamberProperty("skydoves") // ChamberProperty can be initialized with any object.
76+
@ShareProperty(key = "name") // name is a key name.
77+
private var username = ChamberProperty("skydoves") // ChamberProperty can be initialized with any object.
7678
```
7779

7880
#### setValue
7981
Using the `setValue` method, we can change the `ChamberProperty`'s value.
8082
```kotlin
81-
username.setValue("user name is changed")
83+
username.value = "user name is changed"
8284
```
8385
#### postValue
8486
Posts a task to a main thread to set the given value. So if you have a following code executed in the main thread:
8587
```kotlin
8688
username.postValue("a")
87-
username.setValue("b")
89+
username.value = "b"
8890
```
8991
The value `b` would be set at first and later the main thread would override it with the value `a`.<br>
9092
If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.
9193

9294
#### observe
93-
We can observe the value is changed using the `observe` method.
95+
We can observe the value is changed using the `observe` method. There is only one observer that can be registered on the property. The events are dispatched on the main thread. If `ChamberProperty` already has data set, it will be delivered to the observer.
9496
```kotlin
9597
username.observe {
9698
log("data is changed to $it")
9799
}
98100
```
99101

100102
### ShareLifecycle
101-
Chamber synchronizes the ChamberProperty that has the same scope and same key. <br>
102-
Also pushes a lifecycleOwner to the Chamber's lifecycle stack.<br>
103-
Here is an example that has _MainActivity_ and _SecondActivity_.
103+
Chamber synchronizes and dispatches `ChamberProperty`s that are included in the same scope and had the same key thread-safety. We should pass two arguments; `scopeOwner` that is annotated with a custom scope, `lifecycleOwner` that manages `ChamberProperty`s lifecycles for destroying. Here is an example of _MainActivity_ and _SecondActivity_.
104104

105105
#### MainActivity
106-
__Chamber__ will create a `@UserScope` data holder. <br>
107-
when `Chamber.shareLifecycle` method called, the `name` field that has `nickname` key will be managed by Chamber and Chamber will observe the _MainActivity_'s lifecycle state.
106+
If `Chamber.shareLifecycle` method is called, the `name` property that has `nickname` key will be managed by Chamber and Chamber will observe the _MainActivity_'s lifecycle state.
108107

109108
```kotlin
110109
@UserScope // custom scope
111110
class MainActivity : AppCompatActivity() {
112111

113-
@ShareProperty("nickname")
112+
@ShareProperty(key = "nickname")
114113
private var name = ChamberProperty("skydoves")
115114

116115
override fun onCreate(savedInstanceState: Bundle?) {
@@ -119,20 +118,27 @@ class MainActivity : AppCompatActivity() {
119118

120119
Chamber.shareLifecycle(scopeOwner = this, lifecycleOwner = this)
121120

121+
name.observe { log($it) }
122+
122123
name.value = "name value is changed"
123124

124125
startActivity(SecondActivity::class.java)
125126
}
126127
}
127128
```
129+
```gradle
130+
[output]:
131+
=> skydoves
132+
=> name value is changed
133+
```
128134

129135
#### MainActivity -> SecondActivity
130-
_MainActivity_ starts _SecondActivity_ using startActivity. <br>__Chamber__ will observe the _SecondActivity_'s lifecycle state. And the `name` field's value on the <br>_SecondActivity_ will be updated by __Chamber__ when `shareLifecycle` method called.
136+
_MainActivity_ starts _SecondActivity_ using startActivity. <br>__Chamber__ will observe the _SecondActivity_'s lifecycle state. And the `name` property's value on the <br>_SecondActivity_ will be synchronized by __Chamber__ when `shareLifecycle` method is called.
131137
```kotlin
132138
@UserScope
133139
class SecondActivity : AppCompatActivity() {
134140

135-
@ShareProperty("nickname")
141+
@ShareProperty(key = "nickname")
136142
private var name = ChamberProperty("skydoves")
137143

138144
override fun onCreate(savedInstanceState: Bundle?) {
@@ -141,66 +147,123 @@ class SecondActivity : AppCompatActivity() {
141147

142148
Chamber.shareLifecycle(scopeOwner = this, lifecycleOwner = this)
143149

144-
// the value is "name value is changed". because it was set in MainActivity.
145-
log("name value is .. ${username.value}")
150+
name.observe { log($it) }
146151

147152
name.value = "changed in SecondActivity"
148-
149-
finish()
150153
}
151154
}
152155
```
156+
```gradle
157+
[output]:
158+
=> name value is changed
159+
=> changed in SecondActivity
160+
```
153161

154162
### The process of exiting scope
155163
<p align="center">
156164
<img width="859" alt="chamber02" src="https://user-images.githubusercontent.com/24237865/61709290-d5c39400-ad89-11e9-8008-3466280439ec.png">
157165
</p>
158166

159167
#### SeondActivity -> MainActivity
160-
`finish` method called in _SecondActivity_ and we come back to the _MainActivity_. <br>when _SecondActivity_'s lifecycle state is `onDestroy`, __Chamber__ will not interact anymore with the _SecondActivity_'s `ChamberProperty` and not observe lifecycle state. <br>And when _MainActivity_'s lifecycle state is `onResume`, __Chamber__ will update the `ChamberProperty`'s value in _MainActivity_.
168+
Following the about example, what if we call the `finish()` method in _SecondActivity_ and we come back to the _MainActivity_. <br>when _SecondActivity_'s lifecycle state is `onDestroy`, __Chamber__ will not manage anymore with the _SecondActivity_'s `ChamberProperty` and not observe lifecycle state. <br>And when _MainActivity_'s lifecycle state is `onResume`, __Chamber__ will dispatch the `ChamberProperty`'s value in _MainActivity_.
169+
161170
```kotlin
162171
@UserScope
163172
class MainActivity : AppCompatActivity() {
164173

165-
@ShareProperty("nickname")
174+
@ShareProperty(key = "nickname")
166175
private var name = ChamberProperty("skydoves")
167176

168177
override fun onCreate(savedInstanceState: Bundle?) {
169178
super.onCreate(savedInstanceState)
170179
setContentView(R.layout.activity_second)
171-
172-
// the value is "changed in SecondActivity". because it was set in SecondActivity.
173-
name.observe {
174-
log("name value is .. ${username.value}")
175-
}
180+
181+
Chamber.shareLifecycle(scopeOwner = this, lifecycleOwner = this)
182+
183+
name.observe { log($it) }
184+
185+
name.value = "name value is changed"
186+
187+
startActivity(SecondActivity::class.java)
176188
}
177189
}
178190
```
179-
#### finish MainActivity
180-
After all lifecycle owners are destroyed (all lifecycleOwners are popped from the __Chamber__'s lifecycle stack), the custom scope data space will be cleared in the internal data holder.
191+
```gradle
192+
[output]:
193+
=> changed in SecondActivity
194+
```
195+
#### Destroying a scope
196+
After all lifecycle owners are destroyed (All lifecycleOwners are popped from the __Chamber__'s lifecycle stack), all of the custom scope data will be cleared in the internal Chamber.
181197

182-
### Using on repository pattern
183-
Architecturally, UI components should do work relate to UI works.<br>So it is more preferred to implement Chamber scope class on repository class.
198+
### Usage with ViewModel
199+
Architecturally, UI components should do work relate to UI works.<br>So we can delegate the scope owner to other classes.
184200

185201
```kotlin
186202
@UserScope // custom scope
187-
class MainActivityRepository(lifecycleOwner: LifecycleOwner) {
203+
class MainActivityViewModel : ViewModel() {
188204

189-
@ShareProperty("nickname")
190-
var name = ChamberProperty("skydoves")
205+
@ShareProperty(key = UserScope.nickname)
206+
var username = ChamberProperty("skydoves")
191207

192-
init {
193-
// inject field data and add a lifecycleOwner to the UserScope scope stack.
194-
Chamber.shareLifecycle(scopeOwner = this, lifecycleOwner = lifecycleOwner)
208+
@PropertyObserver(key = UserScope.nickname)
209+
fun usernameObserver(value: String) {
210+
Log.d("MainActivityViewModel", "usernameObserver: $value")
195211
}
196212
}
213+
```
214+
```kotlin
215+
class MainActivity : AppCompatActivity() {
216+
217+
private val viewModel = MainActivityViewModel()
218+
219+
override fun onCreate(savedInstanceState: Bundle?) {
220+
super.onCreate(savedInstanceState)
221+
222+
Chamber.shareLifecycle(scopeOwner = viewModel, lifecycleOwner = this)
223+
}
224+
```
225+
226+
### PropertyObserver
227+
`PropertyObserver` annotation used to observe value changes by `ChamberProperty` that has the same `key` value. This annotation only works with a method that in a scoped class. A method that is annotated with `PropertyObserver` will be invoked, whenever the value changes and receive the value as a parameter. The method must have one parameter and the type must same as the generic of the `ChamberProperty`. <br>
197228

229+
Here is an example of usages in a ViewModel.
230+
```kotlin
231+
@UserScope // custom scope
232+
class MainActivityViewModel : ViewModel() {
233+
234+
@ShareProperty(key = UserScope.nickname)
235+
var username = ChamberProperty("skydoves")
236+
237+
@PropertyObserver(key = UserScope.nickname)
238+
fun usernameObserver(value: String) {
239+
Log.d("MainActivityViewModel", "usernameObserver: $value")
240+
}
241+
}
242+
```
243+
Here is an example of usages in an Activity.
244+
```kotlin
245+
@UserScope
198246
class MainActivity : AppCompatActivity() {
199247

200-
private val repository = MainActivityRepository(this)
248+
@ShareProperty(key = UserScope.nickname)
249+
private var username = chamberProperty("skydoves")
250+
251+
override fun onCreate(savedInstanceState: Bundle?) {
252+
super.onCreate(savedInstanceState)
253+
254+
shareLifecycle()
255+
256+
username.observe { Log.d("SecondActivity", "observed data: $it") }
257+
258+
username.value = "skydoves on SecondActivity"
259+
}
201260

202-
// ...
261+
@PropertyObserver(key = UserScope.nickname)
262+
fun nickNameObserver(nickname: String) {
263+
Log.d("MainActivity", "nickNameObserver: $nickname")
264+
}
203265
}
266+
204267
```
205268

206269
## Find this library useful? :heart:

app/src/main/java/com/skydoves/chamberdemo/MainActivity.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ class MainActivity : AppCompatActivity() {
3232

3333
val binding = ActivityMainBinding.inflate(layoutInflater)
3434
setContentView(binding.root)
35-
36-
// inject field data and add a lifecycleOwner to the UserScope scope stack.
35+
3736
Chamber.shareLifecycle(scopeOwner = viewModel, lifecycleOwner = this)
3837

3938
viewModel.username.observe { Log.d("MainActivity", "observed data: $it") }

chamber/src/main/java/com/skydoves/chamber/ChamberProperty.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class ChamberProperty<T> constructor(value: T) : LifecycleObserver {
118118

119119
/**
120120
* Sets the given observer [ChamberPropertyObserver] for observing value changes.
121-
* There is only one observer who can be registered by the property.
121+
* There is only one observer that can be registered on the property.
122122
*
123123
* The events are dispatched on the main thread. If [ChamberProperty] already has data
124124
* set, it will be delivered to the observer.

0 commit comments

Comments
 (0)