You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
14
14
</p>
15
15
16
-
> <palign="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
+
> <palign="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>
17
17
18
18
><palign="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>
19
19
@@ -42,7 +42,7 @@ allprojects {
42
42
And add a dependency code to your module's build.gradle file.
Chamber is scoped data holder with custom scopes that are lifecycle aware.
59
+
Chamber is a lightweight lifecycle-aware pipeline based on scopes.
60
+
60
61
### ChamberScope
61
62
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
+
63
65
```kotlin
64
66
@ChamberScope
65
67
@Retention(AnnotationRetention.RUNTIME)
66
68
annotationclassUserScope
67
69
```
68
70
69
71
### 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.
72
74
73
75
```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
+
privatevar username =ChamberProperty("skydoves") // ChamberProperty can be initialized with any object.
76
78
```
77
79
78
80
#### setValue
79
81
Using the `setValue` method, we can change the `ChamberProperty`'s value.
80
82
```kotlin
81
-
username.setValue("user name is changed")
83
+
username.value ="user name is changed"
82
84
```
83
85
#### postValue
84
86
Posts a task to a main thread to set the given value. So if you have a following code executed in the main thread:
85
87
```kotlin
86
88
username.postValue("a")
87
-
username.setValue("b")
89
+
username.value ="b"
88
90
```
89
91
The value `b` would be set at first and later the main thread would override it with the value `a`.<br>
90
92
If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.
91
93
92
94
#### 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.
94
96
```kotlin
95
97
username.observe {
96
98
log("data is changed to $it")
97
99
}
98
100
```
99
101
100
102
### 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_.
104
104
105
105
#### 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.
108
107
109
108
```kotlin
110
109
@UserScope // custom scope
111
110
classMainActivity : AppCompatActivity() {
112
111
113
-
@ShareProperty("nickname")
112
+
@ShareProperty(key ="nickname")
114
113
privatevar name =ChamberProperty("skydoves")
115
114
116
115
overridefunonCreate(savedInstanceState:Bundle?) {
@@ -119,20 +118,27 @@ class MainActivity : AppCompatActivity() {
_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.
131
137
```kotlin
132
138
@UserScope
133
139
classSecondActivity : AppCompatActivity() {
134
140
135
-
@ShareProperty("nickname")
141
+
@ShareProperty(key ="nickname")
136
142
privatevar name =ChamberProperty("skydoves")
137
143
138
144
overridefunonCreate(savedInstanceState:Bundle?) {
@@ -141,66 +147,123 @@ class SecondActivity : AppCompatActivity() {
`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
+
161
170
```kotlin
162
171
@UserScope
163
172
classMainActivity : AppCompatActivity() {
164
173
165
-
@ShareProperty("nickname")
174
+
@ShareProperty(key ="nickname")
166
175
privatevar name =ChamberProperty("skydoves")
167
176
168
177
overridefunonCreate(savedInstanceState:Bundle?) {
169
178
super.onCreate(savedInstanceState)
170
179
setContentView(R.layout.activity_second)
171
-
172
-
// the value is "changed in SecondActivity". because it was set in SecondActivity.
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.
181
197
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.
`PropertyObserver` annotation used to observe value changes by `ChamberProperty` that has the same `key` value. Thisannotation 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>
0 commit comments