├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── github │ │ └── lzyzsd │ │ └── rxexamples │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── lzyzsd │ │ │ └── rxexamples │ │ │ ├── DemoUtils.java │ │ │ ├── MainActivity.java │ │ │ ├── NetworkService.java │ │ │ └── operators │ │ │ ├── LiftDemo.java │ │ │ └── TransformDemo.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── github │ └── lzyzsd │ └── rxexamples │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | #built application files 2 | *.apk 3 | *.ap_ 4 | 5 | 6 | # files for the dex VM 7 | *.dex 8 | 9 | 10 | # Java class files 11 | *.class 12 | 13 | 14 | # generated files 15 | bin/ 16 | gen/ 17 | 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | 23 | # Windows thumbnail db 24 | Thumbs.db 25 | 26 | 27 | # OSX files 28 | .DS_Store 29 | 30 | 31 | # Eclipse project files 32 | .classpath 33 | .project 34 | 35 | 36 | # Android Studio 37 | .idea 38 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs. 39 | .gradle 40 | build/ 41 | 42 | 43 | # Signing files 44 | .signing/ 45 | 46 | 47 | # User-specific configurations 48 | .idea/libraries/ 49 | .idea/workspace.xml 50 | .idea/tasks.xml 51 | .idea/.name 52 | .idea/compiler.xml 53 | .idea/copyright/profiles_settings.xml 54 | .idea/encodings.xml 55 | .idea/misc.xml 56 | .idea/modules.xml 57 | .idea/scopes/scope_settings.xml 58 | .idea/vcs.xml 59 | *.iml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Some RxJava & RxAndroid use cases. 2 | 3 | Hope it can help understand Rx better. -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'me.tatarka.retrolambda' 3 | 4 | android { 5 | compileSdkVersion 23 6 | buildToolsVersion "23.0.2" 7 | 8 | defaultConfig { 9 | applicationId "com.github.lzyzsd.rxexamples" 10 | minSdkVersion 15 11 | targetSdkVersion 23 12 | versionCode 1 13 | versionName "1.0" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | compileOptions { 22 | sourceCompatibility JavaVersion.VERSION_1_8 23 | targetCompatibility JavaVersion.VERSION_1_8 24 | } 25 | } 26 | 27 | dependencies { 28 | compile fileTree(dir: 'libs', include: ['*.jar']) 29 | testCompile 'junit:junit:4.12' 30 | compile 'io.reactivex:rxjava:1.0.14' 31 | compile 'io.reactivex:rxandroid:1.0.1' 32 | compile 'com.jakewharton:butterknife:7.0.1' 33 | compile 'com.f2prateek.rx.preferences:rx-preferences:1.0.1' 34 | compile 'com.jakewharton.rxbinding:rxbinding:0.3.0' 35 | } 36 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/bruce/Downloads/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/github/lzyzsd/rxexamples/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.rxexamples; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/lzyzsd/rxexamples/DemoUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.rxexamples; 2 | 3 | import rx.Observable; 4 | import rx.Subscriber; 5 | 6 | /** 7 | * Created by bruce on 11/20/15. 8 | */ 9 | public class DemoUtils { 10 | private static int random() { 11 | return (int)(2000 * Math.random()); 12 | } 13 | 14 | public static Observable createObservable1() { 15 | return Observable.create(new Observable.OnSubscribe() { 16 | @Override 17 | public void call(Subscriber subscriber) { 18 | System.out.println("observable1 produce a"); 19 | subscriber.onNext("a"); 20 | sleep(random()); 21 | System.out.println("observable1 produce b"); 22 | subscriber.onNext("b"); 23 | sleep(random()); 24 | System.out.println("observable1 produce c"); 25 | subscriber.onNext("c"); 26 | sleep(random()); 27 | System.out.println("observable1 produce d"); 28 | subscriber.onNext("d"); 29 | subscriber.onCompleted(); 30 | } 31 | }); 32 | } 33 | 34 | public static Observable createObservable2() { 35 | return Observable.create(new Observable.OnSubscribe() { 36 | @Override 37 | public void call(Subscriber subscriber) { 38 | System.out.println("observable2 produce e"); 39 | subscriber.onNext("e"); 40 | sleep(random()); 41 | System.out.println("observable2 produce f"); 42 | subscriber.onNext("f"); 43 | sleep(random()); 44 | System.out.println("observable2 produce g"); 45 | subscriber.onNext("g"); 46 | sleep(random()); 47 | System.out.println("observable2 produce h"); 48 | subscriber.onNext("h"); 49 | subscriber.onCompleted(); 50 | } 51 | }); 52 | } 53 | 54 | private static void sleep(long time) { 55 | try { 56 | Thread.sleep(time); 57 | } catch (InterruptedException e) { 58 | e.printStackTrace(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/lzyzsd/rxexamples/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.rxexamples; 2 | 3 | import android.app.Activity; 4 | import android.content.SharedPreferences; 5 | import android.os.Bundle; 6 | import android.os.SystemClock; 7 | import android.preference.PreferenceManager; 8 | import android.text.TextUtils; 9 | import android.view.View; 10 | import android.widget.CheckBox; 11 | import android.widget.CompoundButton; 12 | 13 | import com.f2prateek.rx.preferences.Preference; 14 | import com.f2prateek.rx.preferences.RxSharedPreferences; 15 | import com.github.lzyzsd.rxexamples.operators.TransformDemo; 16 | import com.jakewharton.rxbinding.view.RxView; 17 | import com.jakewharton.rxbinding.widget.RxCompoundButton; 18 | 19 | import java.util.concurrent.TimeUnit; 20 | 21 | import butterknife.ButterKnife; 22 | import butterknife.OnClick; 23 | import rx.Observable; 24 | import rx.Subscriber; 25 | import rx.Subscription; 26 | import rx.android.schedulers.AndroidSchedulers; 27 | import rx.functions.Action1; 28 | import rx.schedulers.Schedulers; 29 | 30 | public class MainActivity extends Activity { 31 | 32 | @OnClick(R.id.btn_run_concat) 33 | public void onRunConcatClick(View view) { 34 | testConcat(); 35 | } 36 | 37 | @OnClick(R.id.btn_run_merge) 38 | public void onRunMergeClick(View view) { 39 | testMerge(); 40 | } 41 | 42 | RxSharedPreferences rxPreferences; 43 | 44 | @Override 45 | protected void onCreate(Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | setContentView(R.layout.activity_main); 48 | 49 | SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); 50 | rxPreferences = RxSharedPreferences.create(preferences); 51 | 52 | ButterKnife.bind(this); 53 | 54 | testThrottle(); 55 | 56 | testCompoundButtonWithPreference(); 57 | 58 | Observable.create(new Observable.OnSubscribe() { 59 | @Override 60 | public void call(Subscriber subscriber) { 61 | printThread(0); 62 | subscriber.onNext("ccc"); 63 | subscriber.onCompleted(); 64 | } 65 | }).subscribeOn(Schedulers.newThread()) 66 | .doOnNext(s -> printThread(1)) 67 | .observeOn(Schedulers.io()) 68 | .observeOn(Schedulers.newThread()) 69 | .doOnNext(s -> { 70 | printThread(2); 71 | }) 72 | .subscribeOn(Schedulers.io()) 73 | .doOnNext(s -> { 74 | printThread(4); 75 | }) 76 | .observeOn(Schedulers.io()) 77 | .subscribe(s -> { 78 | printThread(3); 79 | }); 80 | } 81 | 82 | private void printThread(int i) { 83 | System.out.println("------"+i+"----"+Thread.currentThread().getId()+Thread.currentThread().getName()); 84 | } 85 | 86 | private void testCompoundButtonWithPreference() { 87 | Preference checked = rxPreferences.getBoolean("checked", true); 88 | 89 | CheckBox checkBox = (CheckBox) findViewById(R.id.cb_test); 90 | RxCompoundButton.checkedChanges(checkBox) 91 | .subscribe(checked.asAction()); 92 | 93 | checked.asObservable().subscribe(aBoolean -> { 94 | System.out.println("----------------checked: " + aBoolean); 95 | }); 96 | } 97 | 98 | //拼接两个Observable的输出,保证顺序,按照Observable在concat中的顺序,依次将每个Observable产生的事件传递给订阅者 99 | //只有当前面的Observable结束了,才会执行后面的 100 | private void testConcat() { 101 | Observable observable1 = DemoUtils.createObservable1().subscribeOn(Schedulers.newThread()); 102 | Observable observable2 = DemoUtils.createObservable2().subscribeOn(Schedulers.newThread()); 103 | 104 | Observable.concat(observable1, observable2) 105 | .subscribeOn(Schedulers.newThread()) 106 | .subscribe(System.out::println); 107 | } 108 | 109 | //拼接两个Observable的输出,不保证顺序,按照事件产生的顺序发送给订阅者 110 | private void testMerge() { 111 | Observable observable1 = DemoUtils.createObservable1().subscribeOn(Schedulers.newThread()); 112 | Observable observable2 = DemoUtils.createObservable2().subscribeOn(Schedulers.newThread()); 113 | 114 | Observable.merge(observable1, observable2) 115 | .subscribeOn(Schedulers.newThread()) 116 | .subscribe(System.out::println); 117 | } 118 | 119 | /** 120 | * 嵌套有依赖 121 | * 需要登陆之后,根据拿到的token去获取消息列表 122 | */ 123 | @OnClick(R.id.btn_login) 124 | public void testNestedDependency(View view) { 125 | NetworkService.getToken("username", "password") 126 | .flatMap(s -> NetworkService.getMessage(s)) 127 | .subscribe(s -> { 128 | System.out.println("message: " + s); 129 | }); 130 | } 131 | 132 | /** 133 | * 一秒内连续点击button,只会响应一次 134 | */ 135 | private void testThrottle() { 136 | RxView.clicks(findViewById(R.id.btn_throttle)) 137 | .throttleFirst(1, TimeUnit.SECONDS) 138 | .subscribe(aVoid -> { 139 | System.out.println("click"); 140 | }); 141 | } 142 | 143 | private String memoryCache = null; 144 | 145 | /** 146 | *取数据,首先检查内存是否有缓存 147 | *然后检查文件缓存中是否有 148 | *最后才从网络中取 149 | *前面任何一个条件满足,就不会执行后面的 150 | */ 151 | @OnClick(R.id.btn_fetch_data) 152 | public void testCache(View view) { 153 | final Observable memory = Observable.create(new Observable.OnSubscribe() { 154 | @Override 155 | public void call(Subscriber subscriber) { 156 | if (memoryCache != null) { 157 | subscriber.onNext(memoryCache); 158 | } else { 159 | subscriber.onCompleted(); 160 | } 161 | } 162 | }); 163 | Observable disk = Observable.create(new Observable.OnSubscribe() { 164 | @Override 165 | public void call(Subscriber subscriber) { 166 | String cachePref = rxPreferences.getString("cache").get(); 167 | if (!TextUtils.isEmpty(cachePref)) { 168 | subscriber.onNext(cachePref); 169 | } else { 170 | subscriber.onCompleted(); 171 | } 172 | } 173 | }); 174 | 175 | Observable network = Observable.just("network"); 176 | 177 | Observable.concat(memory, disk, network) 178 | .first() 179 | .subscribeOn(Schedulers.newThread()) 180 | .subscribe(s -> { 181 | memoryCache = "memory"; 182 | System.out.println("--------------subscribe: " + s); 183 | }); 184 | } 185 | 186 | @OnClick(R.id.btn_test_tranform) 187 | public void testTransform() { 188 | TransformDemo.complexTransform(); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/lzyzsd/rxexamples/NetworkService.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.rxexamples; 2 | 3 | import rx.Observable; 4 | 5 | /** 6 | * Created by bruce on 11/18/15. 7 | */ 8 | public class NetworkService { 9 | public static Observable getToken(String userName, String pwd) { 10 | return Observable.just("token"); 11 | } 12 | 13 | public static Observable getMessage(String token) { 14 | return Observable.just("message"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/lzyzsd/rxexamples/operators/LiftDemo.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.rxexamples.operators; 2 | 3 | import rx.Observable; 4 | import rx.Subscriber; 5 | 6 | /** 7 | * Created by bruce on 11/20/15. 8 | * 展示如何使用lift自定义operator 9 | * 好处是可以让原有的Observable链式调用不被打断,继续保持链式调用的形式 10 | */ 11 | public class LiftDemo { 12 | /** 13 | * 这里展示了如何自定义一个operator,用来将每个发出来的字符串转换成一个整数 14 | */ 15 | public static void createCustomOperator() { 16 | Observable.just("1", "2", "3") 17 | .lift(subscriber -> new Subscriber() { 18 | @Override 19 | public void onCompleted() { 20 | subscriber.onCompleted(); 21 | } 22 | 23 | @Override 24 | public void onError(Throwable e) { 25 | subscriber.onError(e); 26 | } 27 | 28 | @Override 29 | public void onNext(String s) { 30 | subscriber.onNext(Integer.parseInt(s)); 31 | } 32 | }) 33 | .map(i -> i) 34 | .subscribe(System.out::println);//1 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/lzyzsd/rxexamples/operators/TransformDemo.java: -------------------------------------------------------------------------------- 1 | package com.github.lzyzsd.rxexamples.operators; 2 | 3 | import rx.Observable; 4 | 5 | /** 6 | * Created by bruce on 11/20/15. 7 | */ 8 | public class TransformDemo { 9 | public static void complexTransform() { 10 | Observable.just("1", "2", "2", "3", "4", "5") 11 | .map(Integer::parseInt) 12 | .filter(s -> s > 1) 13 | .distinct() 14 | .take(3) 15 | .reduce((integer, integer2) -> integer.intValue() + integer2.intValue()) 16 | .subscribe(System.out::println);//9 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 |