Skip to content

Commit ccaa4f5

Browse files
committed
master
0 parents  commit ccaa4f5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1320
-0
lines changed

.gitignore

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
*.iml
2+
.gradle
3+
/local.properties
4+
/.idea/caches
5+
/.idea/libraries
6+
/.idea/modules.xml
7+
/.idea/workspace.xml
8+
/.idea/navEditor.xml
9+
/.idea/assetWizardSettings.xml
10+
.DS_Store
11+
/build
12+
/captures
13+
.externalNativeBuild

.idea/codeStyles/Project.xml

+29
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/gradle.xml

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations.xml

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

app/build.gradle

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
apply plugin: 'com.android.application'
2+
3+
android {
4+
compileSdkVersion 28
5+
defaultConfig {
6+
applicationId "com.codingwithmitch.rxjavaflatmapexample"
7+
minSdkVersion 21
8+
targetSdkVersion 28
9+
versionCode 1
10+
versionName "1.0"
11+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
12+
}
13+
buildTypes {
14+
release {
15+
minifyEnabled false
16+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
17+
}
18+
}
19+
}
20+
21+
dependencies {
22+
23+
def retrofitVersion = "2.5.0"
24+
def rxjava_version = '2.2.7'
25+
def rxandroid_version = '2.1.1'
26+
def recyclerview_version = "1.0.0"
27+
28+
29+
implementation fileTree(dir: 'libs', include: ['*.jar'])
30+
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
31+
implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
32+
testImplementation 'junit:junit:4.12'
33+
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
34+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
35+
36+
// Retrofit
37+
implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
38+
implementation "com.squareup.retrofit2:converter-gson:$retrofitVersion"
39+
40+
// RxJava
41+
implementation "io.reactivex.rxjava2:rxjava:$rxjava_version"
42+
43+
// RxJava Call Adapter
44+
implementation "com.squareup.retrofit2:adapter-rxjava2:2.5.0"
45+
46+
// RxAndroid
47+
implementation "io.reactivex.rxjava2:rxandroid:$rxandroid_version"
48+
49+
// Recyclerview
50+
implementation "androidx.recyclerview:recyclerview:$recyclerview_version"
51+
}

app/proguard-rules.pro

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.codingwithmitch.rxjavaflatmapexample;
2+
3+
import android.content.Context;
4+
5+
import androidx.test.InstrumentationRegistry;
6+
import androidx.test.runner.AndroidJUnit4;
7+
8+
import org.junit.Test;
9+
import org.junit.runner.RunWith;
10+
11+
import static org.junit.Assert.*;
12+
13+
/**
14+
* Instrumented test, which will execute on an Android device.
15+
*
16+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
17+
*/
18+
@RunWith(AndroidJUnit4.class)
19+
public class ExampleInstrumentedTest {
20+
@Test
21+
public void useAppContext() {
22+
// Context of the app under test.
23+
Context appContext = InstrumentationRegistry.getTargetContext();
24+
25+
assertEquals("com.codingwithmitch.rxjavaflatmapexample", appContext.getPackageName());
26+
}
27+
}

app/src/main/AndroidManifest.xml

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.codingwithmitch.rxjavaflatmapexample">
4+
5+
<uses-permission android:name="android.permission.INTERNET"/>
6+
7+
<application
8+
android:allowBackup="true"
9+
android:icon="@mipmap/ic_launcher"
10+
android:label="@string/app_name"
11+
android:roundIcon="@mipmap/ic_launcher_round"
12+
android:supportsRtl="true"
13+
android:theme="@style/AppTheme">
14+
<activity android:name=".MainActivity">
15+
<intent-filter>
16+
<action android:name="android.intent.action.MAIN" />
17+
18+
<category android:name="android.intent.category.LAUNCHER" />
19+
</intent-filter>
20+
</activity>
21+
</application>
22+
23+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package com.codingwithmitch.rxjavaflatmapexample;
2+
3+
import androidx.appcompat.app.AppCompatActivity;
4+
import androidx.recyclerview.widget.LinearLayoutManager;
5+
import androidx.recyclerview.widget.RecyclerView;
6+
import io.reactivex.Observable;
7+
import io.reactivex.ObservableSource;
8+
import io.reactivex.Observer;
9+
import io.reactivex.android.schedulers.AndroidSchedulers;
10+
import io.reactivex.disposables.CompositeDisposable;
11+
import io.reactivex.disposables.Disposable;
12+
import io.reactivex.functions.Function;
13+
import io.reactivex.functions.Predicate;
14+
import io.reactivex.schedulers.Schedulers;
15+
16+
import android.os.Bundle;
17+
import android.util.Log;
18+
19+
import com.codingwithmitch.rxjavaflatmapexample.models.Comment;
20+
import com.codingwithmitch.rxjavaflatmapexample.models.Post;
21+
import com.codingwithmitch.rxjavaflatmapexample.requests.ServiceGenerator;
22+
23+
import java.util.List;
24+
import java.util.Random;
25+
26+
public class MainActivity extends AppCompatActivity {
27+
28+
private static final String TAG = "MainActivity";
29+
30+
//ui
31+
private RecyclerView recyclerView;
32+
33+
// vars
34+
private CompositeDisposable disposables = new CompositeDisposable();
35+
private RecyclerAdapter adapter;
36+
37+
38+
@Override
39+
protected void onCreate(Bundle savedInstanceState) {
40+
super.onCreate(savedInstanceState);
41+
setContentView(R.layout.activity_main);
42+
recyclerView = findViewById(R.id.recycler_view);
43+
44+
initRecyclerView();
45+
46+
getPostsObservable()
47+
.subscribeOn(Schedulers.io())
48+
.flatMap(new Function<Post, ObservableSource<Post>>() {
49+
@Override
50+
public ObservableSource<Post> apply(Post post) throws Exception {
51+
return getCommentsObservable(post);
52+
}
53+
})
54+
.observeOn(AndroidSchedulers.mainThread())
55+
.subscribe(new Observer<Post>() {
56+
@Override
57+
public void onSubscribe(Disposable d) {
58+
disposables.add(d);
59+
}
60+
61+
@Override
62+
public void onNext(Post post) {
63+
updatePost(post);
64+
}
65+
66+
@Override
67+
public void onError(Throwable e) {
68+
Log.e(TAG, "onError: ", e);
69+
}
70+
71+
@Override
72+
public void onComplete() {
73+
}
74+
});
75+
}
76+
77+
private Observable<Post> getPostsObservable(){
78+
return ServiceGenerator.getRequestApi()
79+
.getPosts()
80+
.subscribeOn(Schedulers.io())
81+
.observeOn(AndroidSchedulers.mainThread())
82+
.flatMap(new Function<List<Post>, ObservableSource<Post>>() {
83+
@Override
84+
public ObservableSource<Post> apply(final List<Post> posts) throws Exception {
85+
adapter.setPosts(posts);
86+
return Observable.fromIterable(posts)
87+
.subscribeOn(Schedulers.io());
88+
}
89+
});
90+
}
91+
92+
private void updatePost(final Post p){
93+
Observable
94+
.fromIterable(adapter.getPosts())
95+
.filter(new Predicate<Post>() {
96+
@Override
97+
public boolean test(Post post) throws Exception {
98+
return post.getId() == p.getId();
99+
}
100+
})
101+
.observeOn(AndroidSchedulers.mainThread())
102+
.subscribe(new Observer<Post>() {
103+
@Override
104+
public void onSubscribe(Disposable d) {
105+
disposables.add(d);
106+
}
107+
108+
@Override
109+
public void onNext(Post post) {
110+
Log.d(TAG, "onNext: updating post: " + post.getId() + ", thread: " + Thread.currentThread().getName());
111+
adapter.updatePost(post);
112+
}
113+
114+
@Override
115+
public void onError(Throwable e) {
116+
Log.e(TAG, "onError: ", e);
117+
}
118+
119+
@Override
120+
public void onComplete() {
121+
}
122+
});
123+
}
124+
125+
private Observable<Post> getCommentsObservable(final Post post){
126+
return ServiceGenerator.getRequestApi()
127+
.getComments(post.getId())
128+
.map(new Function<List<Comment>, Post>() {
129+
@Override
130+
public Post apply(List<Comment> comments) throws Exception {
131+
132+
int delay = ((new Random()).nextInt(5) + 1) * 1000; // sleep thread for x ms
133+
Thread.sleep(delay);
134+
Log.d(TAG, "apply: sleeping thread " + Thread.currentThread().getName() + " for " + String.valueOf(delay)+ "ms");
135+
136+
post.setComments(comments);
137+
return post;
138+
}
139+
})
140+
.subscribeOn(Schedulers.io());
141+
142+
}
143+
144+
private void initRecyclerView(){
145+
adapter = new RecyclerAdapter();
146+
recyclerView.setLayoutManager(new LinearLayoutManager(this));
147+
recyclerView.setAdapter(adapter);
148+
}
149+
150+
@Override
151+
protected void onDestroy() {
152+
super.onDestroy();
153+
disposables.clear();
154+
}
155+
}

0 commit comments

Comments
 (0)