├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── drawable │ │ │ ├── icon.jpg │ │ │ └── ic_launcher_background.xml │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── layout │ │ │ ├── activity_rxbus.xml │ │ │ └── activity_rxbinding.xml │ │ └── values │ │ │ └── strings.xml │ │ ├── java │ │ └── com │ │ │ └── bqt │ │ │ └── test │ │ │ └── rx │ │ │ ├── observer │ │ │ ├── Watcher.java │ │ │ ├── Watched.java │ │ │ ├── ConcreteWatcher.java │ │ │ ├── Person.java │ │ │ ├── ConcreteWatched.java │ │ │ └── ObserverPatternActivity.java │ │ │ ├── retrofit │ │ │ ├── User.java │ │ │ ├── Contributor.java │ │ │ └── GithubApi.java │ │ │ ├── App.java │ │ │ ├── rxbus │ │ │ ├── RxBus.java │ │ │ ├── RxBusActivity.java │ │ │ ├── RxBusTopFragment.java │ │ │ └── RxBusBottomFragment.java │ │ │ ├── plugins │ │ │ ├── RxPermissionsActivity.java │ │ │ ├── RxPermissionsFragmentActivity.java │ │ │ ├── LubanActivity.java │ │ │ └── RxBindingActivity.java │ │ │ ├── operator │ │ │ ├── RetryWithDelay.java │ │ │ ├── CombineOperatorActivity.java │ │ │ ├── CreateOperatorActivity.java │ │ │ ├── FilterOperatorActivity.java │ │ │ └── TransformOperatorActivity.java │ │ │ ├── MainActivity.java │ │ │ └── ui │ │ │ ├── TestActivity3.java │ │ │ ├── TimingActivity.java │ │ │ ├── TestActivity1.java │ │ │ ├── ConcatActivity.java │ │ │ └── TestActivity2.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── README.md ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── .gitignore ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RxJavaDemo 2 | RxJava各种场景使用示例 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baiqiantao/RxJavaDemo/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baiqiantao/RxJavaDemo/HEAD/app/src/main/res/drawable/icon.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baiqiantao/RxJavaDemo/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/observer/Watcher.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.observer; 2 | 3 | public interface Watcher { 4 | void update(String str); 5 | } -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baiqiantao/RxJavaDemo/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/retrofit/User.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.retrofit; 2 | 3 | public class User { 4 | public String name; 5 | public String email; 6 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/observer/Watched.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.observer; 2 | 3 | public interface Watched { 4 | void addWatcher(Watcher watcher); 5 | 6 | void removeWatcher(Watcher watcher); 7 | 8 | void notifyWatchers(String str); 9 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Apr 27 10:34:15 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/observer/ConcreteWatcher.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.observer; 2 | 3 | import android.util.Log; 4 | 5 | public class ConcreteWatcher implements Watcher { 6 | @Override 7 | public void update(String str) { 8 | Log.i("bqt", "观察者收到被观察者的消息:" + str); 9 | } 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/App.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx; 2 | 3 | import android.app.Application; 4 | 5 | public class App extends Application { 6 | private static App mApp; 7 | 8 | @Override 9 | public void onCreate() { 10 | super.onCreate(); 11 | mApp = this; 12 | } 13 | 14 | public static App getAppContext() { 15 | return mApp; 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/retrofit/Contributor.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.retrofit; 2 | 3 | public class Contributor { 4 | public String login; 5 | public long contributions; 6 | 7 | public Contributor() { 8 | } 9 | 10 | public Contributor(String login, long contributions) { 11 | this.login = login; 12 | this.contributions = contributions; 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/observer/Person.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.observer; 2 | 3 | import java.util.List; 4 | 5 | public class Person { 6 | private String name; 7 | private int age; 8 | public List loves; 9 | 10 | public Person(List loves) { 11 | this.loves = loves; 12 | } 13 | 14 | public Person(String name, int age) { 15 | this.name = name; 16 | this.age = age; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return "Person{" + 22 | "name='" + name + '\'' + 23 | ", age=" + age + 24 | '}'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/rxbus/RxBus.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.rxbus; 2 | 3 | import com.jakewharton.rxrelay2.PublishRelay; 4 | import com.jakewharton.rxrelay2.Relay; 5 | 6 | import io.reactivex.BackpressureStrategy; 7 | import io.reactivex.Flowable; 8 | 9 | public class RxBus { 10 | 11 | private final Relay _bus = PublishRelay.create().toSerialized(); 12 | 13 | public void send(Object o) { 14 | _bus.accept(o); 15 | } 16 | 17 | public Flowable asFlowable() { 18 | return _bus.toFlowable(BackpressureStrategy.LATEST); 19 | } 20 | 21 | public boolean hasObservers() { 22 | return _bus.hasObservers(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_rxbus.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/retrofit/GithubApi.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.retrofit; 2 | 3 | import java.util.List; 4 | 5 | import io.reactivex.Observable; 6 | import retrofit2.http.GET; 7 | import retrofit2.http.Path; 8 | 9 | public interface GithubApi { 10 | 11 | @GET("repos/{owner}/{repo}/contributors") 12 | Observable> contributors(@Path("owner") String owner, @Path("repo") String repo); 13 | 14 | @GET("repos/{owner}/{repo}/contributors") 15 | List getContributors(@Path("owner") String owner, @Path("repo") String repo); 16 | 17 | @GET("users/{user}") 18 | Observable user(@Path("user") String user); 19 | 20 | @GET("users/{user}") 21 | User getUser(@Path("user") String user); 22 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 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 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/observer/ConcreteWatched.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.observer; 2 | 3 | import android.util.Log; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class ConcreteWatched implements Watched { 9 | private List list = new ArrayList<>(); 10 | 11 | @Override 12 | public void addWatcher(Watcher watcher) { 13 | if (list.contains(watcher)) { 14 | Log.i("bqt", "失败,被观察者已经注册过此观察者"); 15 | } else { 16 | Log.i("bqt", "成功,被观察者成功注册了此观察者"); 17 | list.add(watcher); 18 | } 19 | } 20 | 21 | @Override 22 | public void removeWatcher(Watcher watcher) { 23 | if (list.contains(watcher)) { 24 | boolean success = list.remove(watcher); 25 | Log.i("bqt", "此观察者解除注册观察者结果:" + (success ? "成功" : "失败")); 26 | } else { 27 | Log.i("bqt", "失败,此观察者并未注册到被观察者"); 28 | } 29 | } 30 | 31 | @Override 32 | public void notifyWatchers(String str) { 33 | for (Watcher watcher : list) { 34 | watcher.update(str); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/rxbus/RxBusActivity.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.rxbus; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | 7 | import com.bqt.test.rx.R; 8 | 9 | public class RxBusActivity extends Activity { 10 | private RxBus rxBus = null; 11 | 12 | @Override 13 | protected void onCreate(@Nullable Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_rxbus); 16 | getFragmentManager().beginTransaction() 17 | .replace(R.id.rxbus_frag_top, new RxBusTopFragment()) 18 | .replace(R.id.rxbus_frag_bottom, new RxBusBottomFragment()) 19 | .commit(); 20 | } 21 | 22 | // This is better done with a DI Library like Dagger 23 | public RxBus getRxBusSingleton() { 24 | if (rxBus == null) { 25 | rxBus = new RxBus(); 26 | } 27 | return rxBus; 28 | } 29 | 30 | static class TapEvent { 31 | public String name; 32 | 33 | TapEvent(String name) { 34 | this.name = name; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea/workspace.xml 38 | .idea/tasks.xml 39 | .idea/gradle.xml 40 | .idea/dictionaries 41 | .idea/libraries 42 | 43 | # Keystore files 44 | *.jks 45 | 46 | # External native build folder generated in Android Studio 2.2 and later 47 | .externalNativeBuild 48 | 49 | # Google Services (e.g. APIs or Firebase) 50 | google-services.json 51 | 52 | # Freeline 53 | freeline.py 54 | freeline/ 55 | freeline_project_description.json 56 | /.idea/ 57 | /gradlew 58 | /gradlew.bat 59 | /.idea 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/plugins/RxPermissionsActivity.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.plugins; 2 | 3 | import android.app.ListActivity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.ArrayAdapter; 8 | import android.widget.ListView; 9 | 10 | import java.util.Arrays; 11 | 12 | public class RxPermissionsActivity extends ListActivity { 13 | 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | String[] array = {"最简单实用的案例,request", 17 | "和 RxView 一起使用,compose + ensure", 18 | "一次请求多个权限", 19 | "观察详细的结果,requestEach、ensureEach", 20 | "观察详细的结果,requestEachCombined 和 ensureEachCombined", 21 | "shouldShowRequestPermissionRationale 和 isGranted 的使用 ",}; 22 | setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, Arrays.asList(array))); 23 | } 24 | 25 | @Override 26 | protected void onListItemClick(ListView l, View v, int position, long id) { 27 | Intent intent = new Intent(this, RxPermissionsFragmentActivity.class); 28 | intent.putExtra("type", position); 29 | startActivity(intent); 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/rxbus/RxBusTopFragment.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.rxbus; 2 | 3 | import android.app.Fragment; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.view.Gravity; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.TextView; 13 | 14 | import java.text.SimpleDateFormat; 15 | import java.util.Date; 16 | import java.util.Locale; 17 | import java.util.Objects; 18 | 19 | public class RxBusTopFragment extends Fragment { 20 | 21 | private RxBus rxBus; 22 | 23 | @Override 24 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 25 | TextView tv = new TextView(getActivity()); 26 | tv.setTextColor(Color.BLUE); 27 | tv.setBackgroundColor(Color.GRAY); 28 | tv.setText("点击后通过RxBus发送事件"); 29 | tv.setGravity(Gravity.CENTER); 30 | tv.setOnClickListener(view -> { 31 | if (rxBus.hasObservers()) { 32 | String data = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss SSS", Locale.getDefault()).format(new Date()); 33 | rxBus.send(new RxBusActivity.TapEvent("包青天 " + data)); 34 | } 35 | }); 36 | return tv; 37 | } 38 | 39 | @Override 40 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 41 | super.onActivityCreated(savedInstanceState); 42 | rxBus = ((RxBusActivity) Objects.requireNonNull(getActivity())).getRxBusSingleton(); 43 | } 44 | } -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "com.bqt.test.rx" 7 | minSdkVersion 17 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | compileOptions { 14 | targetCompatibility 1.8 15 | sourceCompatibility 1.8 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation 'com.android.support:recyclerview-v7:27.1.1' 28 | 29 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' 30 | implementation 'io.reactivex.rxjava2:rxjava:2.x.x' 31 | 32 | implementation 'com.jakewharton.rxrelay2:rxrelay:2.0.0' 33 | 34 | implementation "com.github.akarnokd:rxjava2-extensions:0.16.0" 35 | 36 | implementation "com.squareup.retrofit2:retrofit:2.0.0" 37 | implementation "com.squareup.retrofit2:converter-gson:2.0.0" 38 | implementation "com.squareup.okhttp3:okhttp:3.7.0" 39 | implementation "com.squareup.okhttp3:okhttp-urlconnection:3.0.1" 40 | implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' 41 | 42 | implementation 'top.zibin:Luban:1.1.8' 43 | implementation 'com.github.tbruyelle:rxpermissions:0.10.2' 44 | implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1' 45 | implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2' 46 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/operator/RetryWithDelay.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.operator; 2 | 3 | import android.util.Log; 4 | 5 | import org.reactivestreams.Publisher; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | 9 | import io.reactivex.Flowable; 10 | import io.reactivex.functions.Function; 11 | 12 | public class RetryWithDelay implements Function, Publisher> { 13 | 14 | private final int maxRetry; 15 | private final int retryDelayMillis; 16 | private int tempRetryCount; 17 | 18 | public RetryWithDelay(final int maxRetry, final int retryDelayMillis) { 19 | this.maxRetry = maxRetry; 20 | this.retryDelayMillis = retryDelayMillis; 21 | tempRetryCount = 1; 22 | } 23 | 24 | // this is a notification handler, all that is cared about here is the emission "type" not emission "content" 25 | // only onNext triggers a re-subscription (onError + onComplete kills it) 26 | @Override 27 | public Publisher apply(Flowable inputObservable) { 28 | // it is critical to use inputObservable in the chain for the result ignoring it and doing your own thing will break the sequence 29 | return inputObservable.flatMap(throwable -> { 30 | if (++tempRetryCount < maxRetry) { 31 | // When this Observable calls onNext, the original Observable will be retried (i.e. re-subscribed) 32 | long delay = (long) (Math.pow(2, tempRetryCount) * retryDelayMillis); 33 | Log.i("bqt", String.format("正在执行第 %d 次重试,将耗时 %d ms", tempRetryCount, delay)); 34 | return Flowable.timer(delay, TimeUnit.MILLISECONDS); 35 | } else { 36 | Log.i("bqt", "已达到最大重试次数"); 37 | // Pass an error so the chain is forcibly completed only onNext triggers a re-subscription (onError + onComplete kills it) 38 | return Flowable.error(throwable); 39 | } 40 | }); 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/rxbus/RxBusBottomFragment.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.rxbus; 2 | 3 | import android.app.Fragment; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.TextView; 12 | 13 | import java.util.Objects; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | import io.reactivex.android.schedulers.AndroidSchedulers; 17 | import io.reactivex.disposables.CompositeDisposable; 18 | import io.reactivex.disposables.Disposable; 19 | import io.reactivex.flowables.ConnectableFlowable; 20 | 21 | public class RxBusBottomFragment extends Fragment { 22 | 23 | private RxBus rxbus; 24 | private CompositeDisposable disposable; 25 | private TextView tv; 26 | 27 | @Override 28 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 29 | tv = new TextView(getActivity()); 30 | tv.setTextColor(Color.RED); 31 | tv.setBackgroundColor(Color.YELLOW); 32 | return tv; 33 | } 34 | 35 | @Override 36 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 37 | super.onActivityCreated(savedInstanceState); 38 | rxbus = ((RxBusActivity) Objects.requireNonNull(getActivity())).getRxBusSingleton(); 39 | } 40 | 41 | @Override 42 | public void onStart() { 43 | super.onStart(); 44 | disposable = new CompositeDisposable(); 45 | 46 | ConnectableFlowable tapEventEmitter = rxbus.asFlowable().publish(); 47 | 48 | Disposable disposable1 = tapEventEmitter 49 | .filter(event -> event instanceof RxBusActivity.TapEvent) 50 | .subscribe(event -> tv.append(((RxBusActivity.TapEvent) event).name + "\n")); 51 | 52 | Disposable disposable2 = tapEventEmitter 53 | .publish(stream -> stream.buffer(stream.debounce(200, TimeUnit.MILLISECONDS))) 54 | .observeOn(AndroidSchedulers.mainThread()) 55 | .filter(taps -> taps != null && taps.size() > 0) 56 | //.filter(taps -> taps.get(0) instanceof RxBusActivity.TapEvent) 57 | .subscribe(taps -> tv.append("\t连击次数:" + taps.size() + "\n")); 58 | 59 | this.disposable.add(disposable1); 60 | this.disposable.add(disposable2); 61 | this.disposable.add(tapEventEmitter.connect()); 62 | } 63 | 64 | @Override 65 | public void onStop() { 66 | super.onStop(); 67 | disposable.clear(); 68 | } 69 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx; 2 | 3 | import android.app.ListActivity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.ArrayAdapter; 8 | import android.widget.ListView; 9 | 10 | import com.bqt.test.rx.observer.ObserverPatternActivity; 11 | import com.bqt.test.rx.operator.CreateOperatorActivity; 12 | import com.bqt.test.rx.operator.FilterOperatorActivity; 13 | import com.bqt.test.rx.operator.CombineOperatorActivity; 14 | import com.bqt.test.rx.operator.TransformOperatorActivity; 15 | import com.bqt.test.rx.plugins.LubanActivity; 16 | import com.bqt.test.rx.plugins.RxBindingActivity; 17 | import com.bqt.test.rx.plugins.RxPermissionsActivity; 18 | 19 | import java.util.Arrays; 20 | 21 | public class MainActivity extends ListActivity { 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | String[] array = {"0、传统的观察者模式和使用 rx 写的观察者模式对比", 27 | "1、创建操作符 create just from defer timer interval repeat", 28 | "2、变换操作符 map flatMap concatMap buffer", 29 | "3、过滤操作符 filter distinct throttle debounce timeout", 30 | "4、组合操作符 ", 31 | "5、 ", 32 | "6、 ", 33 | "7、", 34 | "8、Luban 图片压缩", 35 | "9、RxPermissions 动态权限申请", 36 | "10、RxBinding", 37 | "",}; 38 | setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, Arrays.asList(array))); 39 | } 40 | 41 | private int type = 0; 42 | 43 | @Override 44 | protected void onListItemClick(ListView l, View v, int position, long id) { 45 | switch (position) { 46 | case 0: 47 | startActivity(new Intent(this, ObserverPatternActivity.class)); 48 | break; 49 | case 1: //创建操作符 50 | startActivity(new Intent(this, CreateOperatorActivity.class)); 51 | break; 52 | case 2: //变换操作符 53 | startActivity(new Intent(this, TransformOperatorActivity.class)); 54 | break; 55 | case 3: //过滤操作符 56 | startActivity(new Intent(this, FilterOperatorActivity.class)); 57 | break; 58 | case 4: 59 | startActivity(new Intent(this, CombineOperatorActivity.class)); 60 | break; 61 | case 5: 62 | 63 | break; 64 | case 6: 65 | 66 | break; 67 | case 7: 68 | 69 | break; 70 | case 8: 71 | startActivity(new Intent(this, LubanActivity.class)); 72 | break; 73 | case 9: 74 | startActivity(new Intent(this, RxPermissionsActivity.class)); 75 | break; 76 | case 10: 77 | Intent intent = new Intent(this, RxBindingActivity.class); 78 | intent.putExtra("type", (type++) % 4); 79 | startActivity(intent); 80 | break; 81 | 82 | default: 83 | break; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/observer/ObserverPatternActivity.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.observer; 2 | 3 | import android.app.ListActivity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.widget.ArrayAdapter; 8 | import android.widget.ListView; 9 | 10 | import java.util.Arrays; 11 | import java.util.Random; 12 | 13 | import io.reactivex.Observable; 14 | import io.reactivex.ObservableEmitter; 15 | import io.reactivex.ObservableOnSubscribe; 16 | import io.reactivex.Observer; 17 | import io.reactivex.disposables.Disposable; 18 | 19 | public class ObserverPatternActivity extends ListActivity { 20 | private Watcher watcher; 21 | private Watched watched; 22 | 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | String[] array = {"0、被观察者注册观察者", 26 | "1、被观察者取消注册观察者", 27 | "2、被观察者通知观察者", 28 | "3、rx 被观察者 订阅 观察者", 29 | "4、rx 链式调用简化形式", 30 | "5、just 的扩展用法"}; 31 | setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, Arrays.asList(array))); 32 | 33 | watcher = new ConcreteWatcher(); 34 | watched = new ConcreteWatched(); 35 | } 36 | 37 | @Override 38 | protected void onListItemClick(ListView l, View v, int position, long id) { 39 | switch (position) { 40 | case 0: 41 | watched.addWatcher(watcher); 42 | break; 43 | case 1: 44 | watched.removeWatcher(watcher); 45 | break; 46 | case 2: 47 | watched.notifyWatchers("救命啊"); 48 | break; 49 | case 3: 50 | Observable observable = Observable.create(new ObservableOnSubscribe() { 51 | @Override 52 | public void subscribe(ObservableEmitter emitter) { 53 | emitter.onNext("救命啊-------isDisposed=" + emitter.isDisposed());//false 54 | if (new Random().nextBoolean()) emitter.onComplete(); //发送onComplete 55 | else emitter.onError(new Throwable("发送onError")); //发送onComplete或onError事件后就取消注册了 56 | Log.i("bqt", "调用 onComplete 或 onError 后 isDisposed=" + emitter.isDisposed());//true 57 | } 58 | }); 59 | 60 | Observer observer = new Observer() { 61 | @Override 62 | public void onSubscribe(Disposable d) { 63 | Log.i("bqt", "成功订阅-------isDisposed=" + d.isDisposed());//false 64 | } 65 | 66 | @Override 67 | public void onNext(String s) { 68 | Log.i("bqt", "【观察者接收到了事件】onNext:" + s); 69 | } 70 | 71 | @Override 72 | public void onError(Throwable e) { 73 | Log.i("bqt", "对Error事件作出响应:" + e.getMessage()); 74 | } 75 | 76 | @Override 77 | public void onComplete() { 78 | Log.i("bqt", "对Complete事件作出响应"); 79 | } 80 | }; 81 | observable.subscribe(observer);//被观察者注册观察者 82 | break; 83 | case 4: 84 | Observable.just("救命啊") //快速创建并发送1个被观察者对象,相当于执行了onNext("救命啊")、onComplete() 85 | .subscribe(s -> Log.i("bqt", "onNext:" + s), 86 | e -> Log.i("bqt", "onError:" + e.getMessage()), 87 | () -> Log.i("bqt", "onComplete"), 88 | d -> Log.i("bqt", "onSubscribe" + ",isDisposed:" + d.isDisposed())); 89 | Observable.just("救命啊2").subscribe(s -> Log.i("bqt", "onNext:" + s), Throwable::printStackTrace); 90 | break; 91 | case 5: 92 | Observable.just("救命啊", 10086, true, 1.5f, new Person("包青天", 28)) //最多只能发送10个参数 93 | .subscribe(s -> Log.i("bqt", "onNext:" + s), Throwable::printStackTrace); 94 | break; 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bqt/test/rx/ui/TestActivity3.java: -------------------------------------------------------------------------------- 1 | package com.bqt.test.rx.ui; 2 | 3 | import android.app.ListActivity; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.ArrayAdapter; 8 | import android.widget.ListView; 9 | import android.widget.TextView; 10 | 11 | import com.bqt.test.rx.R; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Arrays; 15 | 16 | import io.reactivex.disposables.CompositeDisposable; 17 | import io.reactivex.disposables.Disposable; 18 | 19 | public class TestActivity3 extends ListActivity { 20 | private TextView tv; 21 | private String[] tipsArray; 22 | private Disposable disposable; 23 | private CompositeDisposable compositeDisposable; 24 | 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | tv = new TextView(this); 28 | tv.setTextColor(Color.BLUE); 29 | getListView().addFooterView(tv); 30 | String[] array = {getString(R.string.btn_demo_form_validation_combinel), 31 | 32 | getString(R.string.msg_demo_timeout), 33 | getString(R.string.btn_demo_exponential_backoff), 34 | getString(R.string.btn_demo_rotation_persist), 35 | getString(R.string.btn_demo_volley), 36 | getString(R.string.btn_demo_pagination), 37 | 38 | getString(R.string.btn_demo_pagination_more), 39 | getString(R.string.btn_demo_networkDetector), 40 | getString(R.string.btn_demo_using), 41 | getString(R.string.btn_demo_multicastPlayground), 42 | "",}; 43 | 44 | tipsArray = new String[]{getString(R.string.btn_demo_form_validation_combinel), 45 | 46 | getString(R.string.msg_demo_timeout), 47 | getString(R.string.btn_demo_exponential_backoff), 48 | getString(R.string.btn_demo_rotation_persist), 49 | getString(R.string.btn_demo_volley), 50 | getString(R.string.btn_demo_pagination), 51 | 52 | getString(R.string.btn_demo_pagination_more), 53 | getString(R.string.btn_demo_networkDetector), 54 | getString(R.string.btn_demo_using), 55 | getString(R.string.btn_demo_multicastPlayground), 56 | "",}; 57 | setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array)))); 58 | } 59 | 60 | @Override 61 | protected void onListItemClick(ListView l, View v, int position, long id) { 62 | tv.setText(tipsArray[position]); 63 | switch (position) { 64 | case 0: 65 | _0(); 66 | break; 67 | case 1: 68 | _1(); 69 | break; 70 | case 2: 71 | _2(); 72 | break; 73 | case 3: 74 | _3(); 75 | break; 76 | case 4: 77 | _4(); 78 | break; 79 | case 5: 80 | _5(); 81 | break; 82 | case 6: 83 | _6(); 84 | break; 85 | } 86 | } 87 | 88 | @Override 89 | protected void onDestroy() { 90 | super.onDestroy();//要在onDestroy或onPause中调用dispose()方法,防止内存泄漏 91 | if (disposable != null) { 92 | disposable.dispose(); 93 | } 94 | if (compositeDisposable != null) { 95 | compositeDisposable.clear(); 96 | } 97 | } 98 | 99 | private void _0() { 100 | 101 | } 102 | 103 | private void _1() { 104 | 105 | } 106 | 107 | private void _2() { 108 | 109 | } 110 | 111 | private void _3() { 112 | 113 | } 114 | 115 | private void _4() { 116 | 117 | } 118 | 119 | private void _5() { 120 | 121 | } 122 | 123 | private void _6() { 124 | 125 | } 126 | 127 | private void _7() { 128 | 129 | } 130 | 131 | private void _8() { 132 | 133 | } 134 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_rxbinding.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 17 | 18 | 24 | 25 | 31 | 32 | 38 | 39 | 45 | 46 | 47 | 48 | 52 | 53 | 60 | 61 | 69 | 70 | 78 | 79 | 80 |