Skip to content

Commit cd202c8

Browse files
author
Kaushik Gopal
committed
feat: add double binding text view example + cleanup README
1 parent eeb850d commit cd202c8

File tree

7 files changed

+179
-30
lines changed

7 files changed

+179
-30
lines changed

README.md

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,6 @@ The long operation is simulated by a blocking Thread.sleep call (since this is d
1515

1616
To really see this example shine. Hit the button multiple times and see how the button click (which is a ui operation) is never blocked because the long operation only runs in the background.
1717

18-
### Instant/Auto searching (subject + debounce)
19-
20-
This is a demo of how events can be swallowed in a way that only the last one is respected. A typical example of this is instant search result boxes. As you type the word "Bruce Lee", you don't want to execute searches for B, Br, Bru, Bruce, Bruce , Bruce L ... etc. But rather intelligently wait for a couple of moments, make sure the user has finished typing the whole word, and then shoot out a single call for "Bruce Lee".
21-
22-
As you type in the input box, it will not shoot out log messages at every single input character change, but rather only pick the lastly emitted event (i.e. input) and log that.
23-
24-
This is the debounce/throttleWithTimeout method in RxJava.
25-
2618
### Accumulate calls (buffer)
2719

2820
This is a demo of how events can be accumulated using the "buffer" operation.
@@ -31,45 +23,54 @@ A button is provided and we accumulate the number of clicks on that button, over
3123

3224
If you hit the button once. you'll get message saying the button was hit once. If you hit it 5 times continuosly within a span of 2 seconds, then you get a single log, saying you hit that button 5 times (vs 5 individual logs saying "Button hit once").
3325

34-
Two implementations:
26+
Two possible implementations:
3527

36-
2a. Using a traditional observable - but encompassing the OnClick within the observable
28+
2a. Using a traditional observable - but encompassing the OnClick within the observable (as demoed here)
3729
2b. Using PublishSubject and sending single clicks to the Observable, which in-turn then sends it to the Observer
3830

31+
### Instant/Auto searching (subject + debounce)
32+
33+
This is a demo of how events can be swallowed in a way that only the last one is respected. A typical example of this is instant search result boxes. As you type the word "Bruce Lee", you don't want to execute searches for B, Br, Bru, Bruce, Bruce , Bruce L ... etc. But rather intelligently wait for a couple of moments, make sure the user has finished typing the whole word, and then shoot out a single call for "Bruce Lee".
34+
35+
As you type in the input box, it will not shoot out log messages at every single input character change, but rather only pick the lastly emitted event (i.e. input) and log that.
36+
37+
This is the debounce/throttleWithTimeout method in RxJava.
38+
3939
### Retrofit and RxJava (zip, flatmap)
4040

41-
[Retrofit from Square](http://square.github.io/retrofit/) is an another amazing library that helps with easy networking (even if you haven't made the jump to RxJava just yet, you really should check it out). It works even better with RxJava and these are examples taken straight up from the android demigod developer Jake Wharton's talk at Netflix. You can [watch the talk](https://www.youtube.com/watch?v=aEuNBk1b5OE#t=2480) at this link. Incidentally, my motiviation to use RxJava was from attending this talk at Netflix.
41+
[Retrofit from Square](http://square.github.io/retrofit/) is an amazing library that helps with easy networking (even if you haven't made the jump to RxJava just yet, you really should check it out). It works even better with RxJava and these are examples hitting the github api, taken straight up from the android demigod-developer Jake Wharton's talk at Netflix. You can [watch the talk](https://www.youtube.com/watch?v=aEuNBk1b5OE#t=2480) at this link. Incidentally, my motiviation to use RxJava was from attending this talk at Netflix.
4242

43-
Since it was a presentation, Jake only put up the most important code snippets in [his slides](https://speakerdeck.com/jakewharton/2014-1). Also he uses Java 8 in them, so I flushed those examples out in ~~good~~ old Java 6.
43+
Since it was a presentation, Jake only put up the most important code snippets in [his slides](https://speakerdeck.com/jakewharton/2014-1). Also he uses Java 8 in them, so I flushed those examples out in ~~good~~ old Java 6. (Note: you're most likely to hit the github api quota pretty fast so send in an oauth-token as a parameter if you want to keep running these examples often).
4444

45-
## Work in Progress:
45+
### Orchestrating Observables. Make parallel network calls, then combine the result into a single data point (flatmap + zip)
4646

47-
### First retrieve from cached data, then make a network call if you can't find your data (concat) (wip)
47+
The below ascii diagram expresses the intention of our next example with panache. f1,f2,3,f4,f5 are essentially network calls that when made, give back a result that' needed for a future calculation.
4848

49-
[Courtesy: gist](https://gist.github.com/adelnizamutdinov/7483969)
5049

51-
### Make two parallel network calls, then combine the result into a single data point (zip) (wip)
50+
(flatmap)
51+
f1 ___________________ f3 _______
52+
(flatmap) | (zip)
53+
f2 ___________________ f4 _______| ___________ final output
54+
\ |
55+
\____________ f5 _______|
5256

53-
[Courtesy: gist](https://gist.github.com/adelnizamutdinov/7483969)
54-
http://www.programmableweb.com/category/all/apis?order=field_popularity
57+
The code for this example has already been written by one Mr.skehlet in the interwebs. Head over to [the gist](https://gist.github.com/skehlet/9418379) for the code. It's written in pure Java (6) so it's pretty comprehensible if you've understood the previous examples. I'll flush it out here again when time permits, and I find a lack of other compelling examples.
5558

56-
### Orchestrating Observables (flatmap + zip) (wip)
59+
### Double binding with TextViews ()
5760

58-
If actions A and B depend on action X running; and action C depends on action Y running. What if you want to combine the result of all those calls and have a single output?
5961

60-
____________ A ________________
61-
(flatmap) / | (zip all 3)
62-
X ------------/_____________ B ________________| ----------- > Ouput
63-
|
64-
Y ------------------------- C ________________|
6562

66-
### Pagination (zip) (wip)
6763

68-
a. Simple pagination
69-
b. Optimized pagination
64+
## Work in Progress:
65+
66+
### First retrieve from cached data, if no cache found make a network call if you can't find your data (concat) (wip)
67+
[Courtesy: gist](https://gist.github.com/adelnizamutdinov/7483969)
7068

69+
### Pagination (wip)
7170

71+
a. Simple pagination
72+
b. Optimized pagination
7273

73-
### Replacing your event Bus (wip)
74+
### Event Bus with RxJAva (wip)
7475

7576
http://stackoverflow.com/questions/19266834/rxjava-and-random-sporadic-events-on-android
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.morihacky.android.rxjava;
2+
3+
import android.content.Context;
4+
import android.os.Bundle;
5+
import android.support.annotation.Nullable;
6+
import android.support.v4.app.Fragment;
7+
import android.view.LayoutInflater;
8+
import android.view.View;
9+
import android.view.ViewGroup;
10+
import android.view.inputmethod.InputMethodManager;
11+
import android.widget.EditText;
12+
import android.widget.TextView;
13+
import butterknife.ButterKnife;
14+
import butterknife.InjectView;
15+
import butterknife.OnTextChanged;
16+
import com.google.common.base.Strings;
17+
import com.morihacky.android.rxjava.app.R;
18+
import rx.Subscription;
19+
import rx.functions.Action1;
20+
import rx.subjects.PublishSubject;
21+
22+
public class DoubleBindingTextViewFragment
23+
extends Fragment {
24+
25+
@InjectView(R.id.double_binding_num1) EditText _number1;
26+
@InjectView(R.id.double_binding_num2) EditText _number2;
27+
@InjectView(R.id.double_binding_result) TextView _result;
28+
29+
Subscription _subscription;
30+
PublishSubject<Float> _resultEmitterSubject;
31+
32+
@Override
33+
public View onCreateView(LayoutInflater inflater,
34+
@Nullable ViewGroup container,
35+
@Nullable Bundle savedInstanceState) {
36+
View layout = inflater.inflate(R.layout.fragment_double_binding_textview, container, false);
37+
ButterKnife.inject(this, layout);
38+
39+
_resultEmitterSubject = PublishSubject.create();
40+
_subscription = _resultEmitterSubject.asObservable().subscribe(new Action1<Float>() {
41+
@Override
42+
public void call(Float aFloat) {
43+
_result.setText(String.valueOf(aFloat));
44+
}
45+
});
46+
47+
onNumberChanged();
48+
_number2.requestFocus();
49+
50+
return layout;
51+
}
52+
53+
@OnTextChanged({ R.id.double_binding_num1, R.id.double_binding_num2 })
54+
public void onNumberChanged() {
55+
float num1 = 0;
56+
float num2 = 0;
57+
58+
if (!Strings.isNullOrEmpty(_number1.getText().toString())) {
59+
num1 = Float.parseFloat(_number1.getText().toString());
60+
}
61+
62+
if (!Strings.isNullOrEmpty(_number2.getText().toString())) {
63+
num2 = Float.parseFloat(_number2.getText().toString());
64+
}
65+
66+
_resultEmitterSubject.onNext(num1 + num2);
67+
}
68+
69+
@Override
70+
public void onDestroyView() {
71+
super.onDestroyView();
72+
if (_subscription != null) {
73+
_subscription.unsubscribe();
74+
}
75+
}
76+
}

app/src/main/java/com/morihacky/android/rxjava/MainActivity.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ protected void onCreate(Bundle savedInstanceState) {
1717

1818
getSupportFragmentManager().beginTransaction().addToBackStack(this.toString())
1919
.replace(R.id.activity_main, new MainFragment(), this.toString())
20-
//.replace(R.id.activity_main, new SubjectDebounceSearchEmitterFragment(), this.toString())
2120
.commit();
2221
}
2322
}

app/src/main/java/com/morihacky/android/rxjava/MainFragment.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ public void demoRetrofitCalls() {
5858
.commit();
5959
}
6060

61+
@OnClick(R.id.btn_demo_double_binding_textview)
62+
public void demoDoubleBindingWithPublishSubject() {
63+
getActivity().getSupportFragmentManager()
64+
.beginTransaction()
65+
.addToBackStack(this.toString())
66+
.replace(R.id.activity_main, new DoubleBindingTextViewFragment(), this.toString())
67+
.commit();
68+
}
69+
6170
//@OnClick(R.id.btn_demo_subject_timeout)
6271
public void demoTimeout() {
6372
getActivity().getSupportFragmentManager()
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<LinearLayout
4+
android:orientation="vertical"
5+
android:layout_height="match_parent"
6+
android:layout_width="match_parent"
7+
xmlns:android="http://schemas.android.com/apk/res/android">
8+
9+
<TextView
10+
android:layout_height="wrap_content"
11+
android:layout_width="match_parent"
12+
android:padding="10dp"
13+
android:gravity="center"
14+
android:text="@string/msg_demo_doublebinding"/>
15+
16+
<LinearLayout
17+
android:layout_height="wrap_content"
18+
android:layout_width="match_parent"
19+
android:layout_marginTop="10dp">
20+
21+
<EditText
22+
android:id="@+id/double_binding_num1"
23+
android:layout_weight="1"
24+
android:layout_height="50dp"
25+
android:layout_width="0dp"
26+
android:gravity="center"
27+
android:inputType="numberDecimal"
28+
android:text="100"/>
29+
30+
<TextView
31+
android:layout_weight="1"
32+
android:layout_height="50dp"
33+
android:layout_width="0dp"
34+
android:gravity="center"
35+
android:text="+"/>
36+
37+
<EditText
38+
android:id="@+id/double_binding_num2"
39+
android:layout_weight="1"
40+
android:layout_height="50dp"
41+
android:layout_width="0dp"
42+
android:inputType="numberDecimal"
43+
android:gravity="center"
44+
android:text="8"/>
45+
</LinearLayout>
46+
47+
<TextView
48+
android:id="@+id/double_binding_result"
49+
android:layout_height="wrap_content"
50+
android:layout_width="match_parent"
51+
android:layout_marginTop="10dp"
52+
android:gravity="center"
53+
android:textSize="45sp"
54+
android:text="0"/>
55+
56+
</LinearLayout>

app/src/main/res/layout/fragment_main.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,11 @@
3838
android:layout_height="wrap_content"
3939
android:layout_width="match_parent"
4040
android:text="@string/btn_demo_retrofit"/>
41+
42+
<Button
43+
android:id="@+id/btn_demo_double_binding_textview"
44+
android:layout_height="wrap_content"
45+
android:layout_width="match_parent"
46+
android:text="@string/btn_demo_double_binding_textview"/>
4147
</LinearLayout>
4248
</ScrollView>

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@
1616
<string name="btn_demo_subject_debounce">search text listener(subject debouncing)</string>
1717
<string name="btn_demo_timeout">delayed jobs (timeout)</string>
1818
<string name="btn_demo_retrofit">Retrofit + RxJava</string>
19+
<string name="btn_demo_double_binding_textview">Double binding (PublishSubject)</string>
20+
<string name="msg_demo_doublebinding">The "technique" used here is more useful than the wonderful calculation achieved below. Using this mechanism you can achieve something simliar to AngularJs or the ViewModel pattern pretty easily.</string>
1921
</resources>

0 commit comments

Comments
 (0)