Skip to content

Commit 10fa255

Browse files
committed
Add full example for Activity + retained fragment + cache
1 parent ffffa57 commit 10fa255

File tree

8 files changed

+145
-88
lines changed

8 files changed

+145
-88
lines changed

rxjava-contrib/rxjava-android-samples/samples/src/main/AndroidManifest.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
package="com.netflix.rxjava.android.samples" >
44

55
<application
6+
android:name=".SamplesApplication"
67
android:allowBackup="true"
78
android:icon="@drawable/ic_launcher"
89
android:theme="@style/AppTheme"
910
android:label="@string/app_name">
1011
<activity
11-
android:name=".SampleFragmentActivity">
12+
android:name=".RetainedFragmentActivity">
1213

1314
<intent-filter>
1415
<category android:name="android.intent.category.LAUNCHER"/>

rxjava-contrib/rxjava-android-samples/samples/src/main/java/com/netflix/rxjava/android/samples/RetainedFragment.java

Lines changed: 0 additions & 65 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package com.netflix.rxjava.android.samples;
2+
3+
import android.app.Activity;
4+
import android.app.Fragment;
5+
import android.os.Bundle;
6+
import android.view.LayoutInflater;
7+
import android.view.View;
8+
import android.view.ViewGroup;
9+
import android.view.Window;
10+
import android.widget.TextView;
11+
12+
import org.json.JSONException;
13+
import org.json.JSONObject;
14+
15+
import rx.Observable;
16+
import rx.Subscription;
17+
import rx.android.schedulers.AndroidSchedulers;
18+
import rx.functions.Action1;
19+
import rx.functions.Func1;
20+
import rx.subscriptions.Subscriptions;
21+
22+
/**
23+
* Problem:
24+
* You have a data source (where that data is potentially expensive to obtain), and you want to
25+
* emit this data into a fragment. However, you want to gracefully deal with rotation changes and
26+
* not lose any data already emitted.
27+
* <p/>
28+
* Solution:
29+
* Combine {@link android.app.Fragment#setRetainInstance(boolean)} with
30+
* {@link rx.android.schedulers.AndroidSchedulers#mainThread()} and {@link rx.Observable#cache()}
31+
*/
32+
public class RetainedFragmentActivity extends Activity {
33+
34+
@Override
35+
protected void onCreate(Bundle savedInstanceState) {
36+
super.onCreate(savedInstanceState);
37+
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
38+
setTitle("Fake API call");
39+
setContentView(R.layout.retained_fragment_activity);
40+
}
41+
42+
@SuppressWarnings("ConstantConditions")
43+
public static class RetainedFragment extends Fragment {
44+
45+
// in a production app, you don't want to have JSON parser code in your fragment,
46+
// but we'll simplify a little here
47+
private static final Func1<String, String> PARSE_JSON = new Func1<String, String>() {
48+
@Override
49+
public String call(String json) {
50+
try {
51+
JSONObject jsonObject = new JSONObject(json);
52+
return String.valueOf(jsonObject.getInt("result"));
53+
} catch (JSONException e) {
54+
throw new RuntimeException(e);
55+
}
56+
}
57+
};
58+
59+
private Observable<String> strings;
60+
private Subscription subscription = Subscriptions.empty();
61+
62+
public RetainedFragment() {
63+
setRetainInstance(true);
64+
}
65+
66+
@Override
67+
public void onCreate(Bundle savedInstanceState) {
68+
super.onCreate(savedInstanceState);
69+
70+
// simulate fetching a JSON document with a latency of 2 seconds
71+
strings = SampleObservables.fakeApiCall(2000).map(PARSE_JSON)
72+
.observeOn(AndroidSchedulers.mainThread())
73+
.cache();
74+
}
75+
76+
@Override
77+
public void onDestroyView() {
78+
subscription.unsubscribe();
79+
super.onDestroyView();
80+
}
81+
82+
@Override
83+
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
84+
getActivity().setProgressBarIndeterminateVisibility(true);
85+
return inflater.inflate(R.layout.retained_fragment, container, false);
86+
}
87+
88+
@Override
89+
public void onViewCreated(final View view, Bundle savedInstanceState) {
90+
super.onViewCreated(view, savedInstanceState);
91+
92+
final TextView textView = (TextView) view.findViewById(android.R.id.text1);
93+
94+
// (re-)subscribe to the sequence, which either emits the cached result or simply re-
95+
// attaches the subscriber to wait for it to arrive
96+
subscription = strings.subscribe(new Action1<String>() {
97+
@Override
98+
public void call(String result) {
99+
textView.setText(result);
100+
getActivity().setProgressBarIndeterminateVisibility(false);
101+
}
102+
});
103+
}
104+
}
105+
}

rxjava-contrib/rxjava-android-samples/samples/src/main/java/com/netflix/rxjava/android/samples/SampleFragmentActivity.java

Lines changed: 0 additions & 17 deletions
This file was deleted.

rxjava-contrib/rxjava-android-samples/samples/src/main/java/com/netflix/rxjava/android/samples/SampleObservables.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.os.SystemClock;
44

55
import rx.Observable;
6+
import rx.Subscriber;
67
import rx.functions.Action1;
78
import rx.functions.Func1;
89
import rx.schedulers.Schedulers;
@@ -12,18 +13,30 @@ public class SampleObservables {
1213
/**
1314
* Emits numbers as strings, where these numbers a generated on a background thread.
1415
*/
15-
public static Observable<String> numberStrings() {
16-
return Observable.range(1, 10).map(new Func1<Integer, String>() {
16+
public static Observable<String> numberStrings(int from, int to, final long delay) {
17+
return Observable.range(from, to).map(new Func1<Integer, String>() {
1718
@Override
1819
public String call(Integer integer) {
1920
return integer.toString();
2021
}
2122
}).doOnNext(new Action1<String>() {
2223
@Override
2324
public void call(String s) {
24-
SystemClock.sleep(1000);
25+
SystemClock.sleep(delay);
2526
}
2627
}).subscribeOn(Schedulers.newThread());
2728
}
2829

30+
public static Observable<String> fakeApiCall(final long delay) {
31+
return Observable.create(new Observable.OnSubscribe<String>() {
32+
@Override
33+
public void call(Subscriber<? super String> subscriber) {
34+
// simulate I/O latency
35+
SystemClock.sleep(delay);
36+
final String fakeJson = "{\"result\": 42}";
37+
subscriber.onNext(fakeJson);
38+
subscriber.onCompleted();
39+
}
40+
}).subscribeOn(Schedulers.io());
41+
}
2942
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.netflix.rxjava.android.samples;
2+
3+
import android.app.Application;
4+
import android.os.StrictMode;
5+
6+
public class SamplesApplication extends Application {
7+
8+
@Override
9+
public void onCreate() {
10+
super.onCreate();
11+
StrictMode.enableDefaults();
12+
}
13+
}

rxjava-contrib/rxjava-android-samples/samples/src/main/res/layout/sample_activity.xml renamed to rxjava-contrib/rxjava-android-samples/samples/src/main/res/layout/retained_fragment_activity.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
xmlns:tools="http://schemas.android.com/tools"
33
android:layout_width="match_parent"
44
android:layout_height="match_parent"
5-
tools:context="com.netflix.rxjava.android.samples.SampleFragmentActivity">
5+
tools:context="com.netflix.rxjava.android.samples.RetainedFragmentActivity">
66

77
<fragment
88
android:tag="retained_fragment"
99
android:layout_width="match_parent"
1010
android:layout_height="match_parent"
11-
android:name="com.netflix.rxjava.android.samples.RetainedFragment"
11+
android:name="com.netflix.rxjava.android.samples.RetainedFragmentActivity$RetainedFragment"
1212
tools:layout="@layout/retained_fragment" />
1313

1414
</RelativeLayout>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<menu xmlns:android="http://schemas.android.com/apk/res/android">
2+
3+
<item android:id="@+id/action_settings"
4+
android:title="@string/action_settings"
5+
android:orderInCategory="100"
6+
android:showAsAction="never" />
7+
</menu>

0 commit comments

Comments
 (0)