diff --git a/.gitignore b/.gitignore
index 39fb081..0d97603 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,6 @@
/build
/captures
.externalNativeBuild
+/.idea/
+/.gradle/
+/.idea/misc.xml
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 7ac24c7..1c370b9 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -9,6 +9,7 @@
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
index deea19e..f48abbb 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -4,6 +4,7 @@
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 2276c4a..b99851b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -27,7 +27,6 @@ dependencies {
compile "com.android.support:appcompat-v7:$supportLibVersion"
compile "com.android.support:design:$supportLibVersion"
- compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.jakewharton:butterknife:8.6.0'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
diff --git a/app/src/main/java/com/nanchen/rxjava2examples/module/rxjava2/operators/item/RxMapActivity.java b/app/src/main/java/com/nanchen/rxjava2examples/module/rxjava2/operators/item/RxMapActivity.java
index 864eda2..0f3aebc 100644
--- a/app/src/main/java/com/nanchen/rxjava2examples/module/rxjava2/operators/item/RxMapActivity.java
+++ b/app/src/main/java/com/nanchen/rxjava2examples/module/rxjava2/operators/item/RxMapActivity.java
@@ -41,6 +41,8 @@ public void subscribe(@NonNull ObservableEmitter e) throws Exception {
e.onNext(3);
}
}).map(new Function() {
+
+
@Override
public String apply(@NonNull Integer integer) throws Exception {
return "This is result " + integer;
diff --git a/build.gradle b/build.gradle
index e5ca779..60f82ab 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,11 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
+ ext.kotlin_version = '1.1.3-2'
repositories {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.2'
+ classpath 'com.android.tools.build:gradle:2.2.1'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index de1ad4e..04e285f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Jun 19 13:39:52 CST 2017
+#Mon Dec 28 10:00:20 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
diff --git a/leakdemo/.gitignore b/leakdemo/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/leakdemo/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/leakdemo/build.gradle b/leakdemo/build.gradle
new file mode 100644
index 0000000..f11c1e4
--- /dev/null
+++ b/leakdemo/build.gradle
@@ -0,0 +1,56 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+android {
+ compileSdkVersion 26
+ buildToolsVersion "26.0.0"
+
+ defaultConfig {
+ applicationId "com.example.leakdemo"
+ minSdkVersion 15
+ targetSdkVersion 26
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ exclude group: 'com.android.support', module: 'support-annotations'
+ })
+ compile 'com.android.support:appcompat-v7:26.+'
+ testCompile 'junit:junit:4.12'
+ compile 'com.jakewharton.timber:timber:4.5.1'
+ compile 'com.squareup.retrofit2:retrofit:2.0.0'
+ compile 'com.squareup.retrofit2:converter-gson:2.0.0'
+ compile 'com.mcxiaoke.volley:library:1.0.19'
+ compile 'io.reactivex.rxjava2:rxjava:2.0.7'
+ // Because RxAndroid releases are few and far between, it is recommended you also
+ // explicitly depend on RxJava's latest version for bug fixes and new features.
+ compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
+ compile 'com.github.akarnokd:rxjava2-extensions:0.16.0'
+ compile 'com.jakewharton.rxrelay2:rxrelay:2.0.0'
+ compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
+ compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
+ debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
+ releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+ testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+ compile 'com.jakewharton:butterknife:8.5.1'
+ annotationProcessor "com.jakewharton:butterknife-compiler:8.5.1"
+ compile 'com.android.support:design:26.0.0-alpha1'
+ compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
+ compile 'com.amitshekhar.android:rx2-android-networking:1.0.0'
+}
+repositories {
+ mavenCentral()
+}
diff --git a/leakdemo/proguard-rules.pro b/leakdemo/proguard-rules.pro
new file mode 100644
index 0000000..3797231
--- /dev/null
+++ b/leakdemo/proguard-rules.pro
@@ -0,0 +1,25 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/zhanghehe/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/leakdemo/src/androidTest/java/com/example/leakdemo/ExampleInstrumentedTest.java b/leakdemo/src/androidTest/java/com/example/leakdemo/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..89d5add
--- /dev/null
+++ b/leakdemo/src/androidTest/java/com/example/leakdemo/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.example.leakdemo;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("com.example.leakdemo", appContext.getPackageName());
+ }
+}
diff --git a/leakdemo/src/main/AndroidManifest.xml b/leakdemo/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ee510f3
--- /dev/null
+++ b/leakdemo/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/leakdemo/src/main/java/com/example/leakdemo/MainActivity.java b/leakdemo/src/main/java/com/example/leakdemo/MainActivity.java
new file mode 100644
index 0000000..96cd7a2
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/MainActivity.java
@@ -0,0 +1,55 @@
+package com.example.leakdemo;
+
+import android.os.AsyncTask;
+import android.os.SystemClock;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+import com.example.leakdemo.fragments.MainFragment;
+import com.example.leakdemo.rxbus.RxBus;
+
+public class MainActivity extends AppCompatActivity {
+
+
+ private RxBus rxBus;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState==null) {
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(android.R.id.content,new MainFragment(),this.toString())
+ .commit();
+ }
+ }
+
+ public RxBus getRxBusSingleton(){
+ if(rxBus==null){
+ rxBus=new RxBus();
+ }
+ return rxBus;
+
+ }
+
+ private void removeWorkerFragments(){
+// Fragment frag=getSupportFragmentManager()
+// .findFragmentByTag(RotationPersist1WorkerFragment.class.getName());
+// if (frag != null) {
+// getSupportFragmentManager().beginTransaction().remove(frag).commit();
+// }
+//
+// frag=getSupportFragmentManager().findFragmentByTag(RotationPersist2WorkerFragment
+// .class.getName());
+// if (frag != null) {
+// getSupportFragmentManager().beginTransaction().remove(frag).commit();
+//
+// }
+
+ }
+
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/MyApplication.java b/leakdemo/src/main/java/com/example/leakdemo/MyApplication.java
new file mode 100644
index 0000000..cf8ec77
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/MyApplication.java
@@ -0,0 +1,68 @@
+package com.example.leakdemo;
+
+import android.app.Application;
+
+import com.example.leakdemo.model.Events;
+import com.example.leakdemo.ui.RxBus;
+import com.example.leakdemo.volley.MyVolley;
+import com.squareup.leakcanary.LeakCanary;
+import com.squareup.leakcanary.RefWatcher;
+
+import java.util.concurrent.TimeUnit;
+
+import io.reactivex.Observable;
+import io.reactivex.annotations.NonNull;
+import io.reactivex.functions.Consumer;
+import timber.log.Timber;
+
+/**
+ * Created by zhanghehe on 2017/6/29.
+ */
+
+public class MyApplication extends Application {
+ private static MyApplication instance;
+ private RefWatcher refWatcher;
+ private RxBus bus;
+
+ public static MyApplication get(){
+ return instance;
+ }
+
+ public static RefWatcher getRefWatcher(){
+ return MyApplication.get().refWatcher;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ if(LeakCanary.isInAnalyzerProcess(this)){
+ return;
+ }
+
+ bus=new RxBus();
+
+ instance=(MyApplication)getApplicationContext();
+ refWatcher=LeakCanary.install(this);
+
+ MyVolley.init(this);
+
+ Timber.plant(new Timber.DebugTree());
+
+ }
+
+ public RxBus bus(){
+ return bus;
+ }
+
+ public void sendAutoEvent(){
+ Observable.timer(2, TimeUnit.SECONDS)
+ .subscribe(new Consumer() {
+ @Override
+ public void accept(@NonNull Long aLong) throws Exception {
+ bus.send(new Events.AutoEvent());
+ }
+ });
+ }
+
+
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/base/BaseFragment.java b/leakdemo/src/main/java/com/example/leakdemo/base/BaseFragment.java
new file mode 100644
index 0000000..fdd1dc0
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/base/BaseFragment.java
@@ -0,0 +1,61 @@
+package com.example.leakdemo.base;
+
+import android.os.Bundle;
+import android.os.Looper;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.example.leakdemo.MyApplication;
+import com.squareup.leakcanary.RefWatcher;
+
+import butterknife.ButterKnife;
+import butterknife.Unbinder;
+import io.reactivex.disposables.CompositeDisposable;
+
+/**
+ * Created by zhanghehe on 2017/7/3.
+ */
+
+public abstract class BaseFragment extends Fragment {
+
+ protected CompositeDisposable disposable=new CompositeDisposable();
+ private Unbinder unbinder;
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ RefWatcher refWatcher= MyApplication.getRefWatcher();
+ refWatcher.watch(this);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+
+ View layout=inflater.inflate(layoutResId(),container,false);
+ unbinder=ButterKnife.bind(this,layout);
+ return layout;
+ }
+
+ public abstract int layoutResId();
+
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ unbinder.unbind();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ disposable.clear();
+ }
+
+ protected boolean isCurrentlyOnMainThread(){
+ return Looper.myLooper()==Looper.getMainLooper();
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/bean/Contributor.java b/leakdemo/src/main/java/com/example/leakdemo/bean/Contributor.java
new file mode 100644
index 0000000..023d389
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/bean/Contributor.java
@@ -0,0 +1,10 @@
+package com.example.leakdemo.bean;
+
+/**
+ * Created by zhanghehe on 2017/7/8.
+ */
+
+public class Contributor {
+ public String login;
+ public long contributions;
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/bean/User.java b/leakdemo/src/main/java/com/example/leakdemo/bean/User.java
new file mode 100644
index 0000000..89b0a79
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/bean/User.java
@@ -0,0 +1,33 @@
+package com.example.leakdemo.bean;
+
+import com.example.leakdemo.model.ApiUser;
+
+/**
+ * Created by zhanghehe on 2017/7/8.
+ */
+
+public class User {
+
+ public long id;
+ public String firstname;
+ public String lastname;
+ public boolean isFollowing;
+
+ public User(){}
+
+ public User(ApiUser apiUser){
+ this.id=apiUser.id;
+ this.firstname=apiUser.firstName;
+ this.lastname=apiUser.lastName;
+ }
+
+ @Override
+ public String toString() {
+ return "User{"+
+ "id="+id+
+ ", fitstname='"+firstname+'\''+
+ ", lastname'"+lastname+'\''+
+ ",isFolling="+isFollowing+
+ '}';
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/AsyncSubjectExample.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/AsyncSubjectExample.java
new file mode 100644
index 0000000..c3e251a
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/AsyncSubjectExample.java
@@ -0,0 +1,59 @@
+package com.example.leakdemo.fragments;
+
+
+import io.reactivex.Observer;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.subjects.AsyncSubject;
+
+/**
+ * Created by zhanghehe on 2017/8/13.
+ */
+
+public class AsyncSubjectExample extends Base3Fragment{
+ @Override
+ public void doSomeClick() {
+
+ AsyncSubject subject=AsyncSubject.create();
+
+
+ subject.subscribe(getObserver("First:"));
+
+ subject.onNext(1);
+ subject.onNext(3);
+ subject.onNext(4);
+ subject.onNext(5);
+
+ subject.subscribe(getObserver("Second:"));
+
+ subject.onNext(7);
+ subject.onComplete();
+
+ }
+
+ private Observer super Integer> getObserver(final String s) {
+ return new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addText(s+"onSubScribe"+d.isDisposed());
+ }
+
+ @Override
+ public void onNext(Integer integer) {
+ addText(s+"onNext"+integer);
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ addText(s+"onError"+e.getMessage());
+
+ }
+
+ @Override
+ public void onComplete() {
+ addText(s+"onCOmplete");
+
+ }
+ };
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/Base2Fragment.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/Base2Fragment.java
new file mode 100644
index 0000000..425b7e4
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/Base2Fragment.java
@@ -0,0 +1,50 @@
+package com.example.leakdemo.fragments;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.example.leakdemo.MyApplication;
+import com.example.leakdemo.R;
+import com.squareup.leakcanary.RefWatcher;
+
+import butterknife.ButterKnife;
+import butterknife.Unbinder;
+
+/**
+ * Created by zhanghehe on 2017/8/1.
+ */
+
+public abstract class Base2Fragment extends Fragment{
+ private Unbinder unbinder;
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ RefWatcher refWatcher= MyApplication.getRefWatcher();
+ refWatcher.watch(this);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+
+ View layout=inflater.inflate(layoutResId(),container,false);
+ unbinder= ButterKnife.bind(this,layout);
+ return layout;
+ }
+
+ protected int layoutResId(){
+ return R.layout.fragment_example;
+ };
+
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ unbinder.unbind();
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/Base3Fragment.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/Base3Fragment.java
new file mode 100644
index 0000000..d8e2ce2
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/Base3Fragment.java
@@ -0,0 +1,31 @@
+package com.example.leakdemo.fragments;
+
+import android.widget.TextView;
+
+import com.example.leakdemo.R;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+
+/**
+ * Created by zhanghehe on 2017/8/13.
+ */
+
+public abstract class Base3Fragment extends Base2Fragment {
+
+ @BindView(R.id.tv)
+ TextView tv;
+ @OnClick(R.id.btn)
+ public void onBtnClick(){
+ doSomeClick();
+ }
+
+ public abstract void doSomeClick() ;
+
+
+
+ public void addText(String s) {
+ tv.append(s);
+ tv.append("\n");
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/BeHaviorSubjectExmaple.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/BeHaviorSubjectExmaple.java
new file mode 100644
index 0000000..6447b0b
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/BeHaviorSubjectExmaple.java
@@ -0,0 +1,56 @@
+package com.example.leakdemo.fragments;
+
+import android.support.v4.app.Fragment;
+
+import io.reactivex.Observer;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.subjects.BehaviorSubject;
+
+/**
+ * Created by zhanghehe on 2017/8/13.
+ */
+
+public class BeHaviorSubjectExmaple extends Base3Fragment {
+ @Override
+ public void doSomeClick() {
+
+ BehaviorSubject source=BehaviorSubject.create();
+
+ source.subscribe(getObserver("First"));
+ source.onNext(1);
+ source.onNext(2);
+ source.onNext(3);
+ source.subscribe(getObserver("Second"));
+
+ source.onNext(4);
+ source.onComplete();
+
+ }
+
+ private Observer super Integer> getObserver(final String s) {
+ return new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addText("onSubscribe"+s+d.isDisposed());
+ }
+
+ @Override
+ public void onNext(Integer integer) {
+ addText("onNext"+s+integer);
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ addText("onErrot"+s+e.getMessage());
+
+ }
+
+ @Override
+ public void onComplete() {
+ addText("onCOmplete"+s);
+
+ }
+ };
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/BufferExampleFragment.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/BufferExampleFragment.java
new file mode 100644
index 0000000..9e88d1f
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/BufferExampleFragment.java
@@ -0,0 +1,75 @@
+package com.example.leakdemo.fragments;
+
+
+import android.widget.TextView;
+
+import com.example.leakdemo.R;
+
+import java.util.List;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import io.reactivex.Observable;
+import io.reactivex.Observer;
+import io.reactivex.disposables.Disposable;
+
+/**
+ * Created by zhanghehe on 2017/8/9.
+ */
+
+public class BufferExampleFragment extends Base2Fragment {
+
+ @BindView(R.id.tv)
+ TextView tv;
+ @OnClick(R.id.btn)
+ public void onClick(){
+ Observable> buffered=getObservable().buffer(3,1);
+
+ buffered.subscribe(getObserver());
+
+ }
+
+ private Observable getObservable(){
+ return Observable.just("one","two","three","four","five");
+ }
+
+ private Observer> getObserver(){
+ return new Observer>() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ tv.append("onSubscribe"+d.isDisposed());
+ tv.append("\n");
+
+ }
+
+ @Override
+ public void onNext(List strings) {
+ tv.append("onNext size"+strings.size());
+ tv.append("\n");
+
+ for (String string : strings) {
+ tv.append(string);
+ tv.append("\n");
+ }
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ tv.append("onError"+e.getMessage());
+ tv.append("\n");
+
+ }
+
+ @Override
+ public void onComplete() {
+ tv.append("onComplete");
+ tv.append("\n");
+
+ }
+
+
+ };
+ }
+
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/BufferFragmen.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/BufferFragmen.java
new file mode 100644
index 0000000..bf3ad1e
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/BufferFragmen.java
@@ -0,0 +1,53 @@
+package com.example.leakdemo.fragments;
+
+import android.support.v4.app.Fragment;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ListView;
+
+import com.example.leakdemo.R;
+import com.example.leakdemo.base.BaseFragment;
+import com.jakewharton.rxbinding2.view.RxView;
+
+import butterknife.BindView;
+import io.reactivex.annotations.NonNull;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.functions.Function;
+
+/**
+ * __ __ _
+ * \ \ / /_ _| |_ _ _ __
+ * \ V / _` | | | | | '_ \
+ * | | (_| | | |_| | | | |
+ * |_|\__,_|_|\__,_|_| |_|
+ * Created by Hades on 2017/7/27.
+ */
+
+public class BufferFragmen extends BaseFragment {
+
+ @BindView(R.id.lstThreadingLog)
+ ListView lstThreadingLog;
+ @BindView(R.id.btnStartOp)
+ Button btnStartOp;
+ @Override
+ public int layoutResId() {
+ return R.layout.fragment_buffer;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+// disposable1=getBufferedDisposable();
+ }
+
+// private Disposable getBufferedDisposable() {
+// return RxView.clicks(btnStartOp).map(new Function() {
+// @Override
+// public Long apply(@NonNull View.OnClickListener onClickListener) throws Exception {
+// return 1L;
+// }
+// });
+// }
+
+
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/CompletableObserverExample.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/CompletableObserverExample.java
new file mode 100644
index 0000000..91d67a8
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/CompletableObserverExample.java
@@ -0,0 +1,61 @@
+package com.example.leakdemo.fragments;
+
+import android.support.v4.app.Fragment;
+import android.widget.TextView;
+
+import com.example.leakdemo.R;
+
+import java.util.concurrent.TimeUnit;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import io.reactivex.Completable;
+import io.reactivex.CompletableObserver;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Created by zhanghehe on 2017/8/9.
+ */
+
+public class CompletableObserverExample extends Base2Fragment {
+
+ private static final java.lang.CharSequence TAG = "CompletableObserverExample";
+ @BindView(R.id.tv)
+ TextView tv;
+ @OnClick(R.id.btn)
+ public void onClick(){
+ Completable completable=Completable.timer(1000, TimeUnit.MILLISECONDS);
+ completable.subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(getCompletabelObserver());
+
+
+ }
+
+ private CompletableObserver getCompletabelObserver() {
+ return new CompletableObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ tv.append(" onSubScribe: "+d.isDisposed());
+
+ }
+
+ @Override
+ public void onComplete() {
+ tv.append(" onComplete");
+ tv.append("\n");
+
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ tv.append(" onError"+e.getMessage());
+ tv.append("\n");
+
+ }
+ };
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/ConcatExampleActivity.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/ConcatExampleActivity.java
new file mode 100644
index 0000000..421a303
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/ConcatExampleActivity.java
@@ -0,0 +1,71 @@
+package com.example.leakdemo.fragments;
+
+
+import android.widget.TextView;
+
+import com.example.leakdemo.R;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import io.reactivex.Observable;
+import io.reactivex.Observer;
+import io.reactivex.disposables.Disposable;
+
+/**
+ * Created by zhanghehe on 2017/8/13.
+ */
+
+public class ConcatExampleActivity extends Base2Fragment {
+
+ @BindView(R.id.tv)
+ TextView tv;
+ @OnClick(R.id.btn)
+ public void onClick(){
+
+ final String[] aStrings={"A1","A2","A3","A4"};
+ final String[] bStrings={"B1","B2","B3"};
+
+ final Observable aObservable=Observable.fromArray(aStrings);
+ final Observable bObservable=Observable.fromArray(bStrings);
+
+
+ Observable.concat(aObservable,bObservable)
+ .subscribe(getObserver());
+
+
+ }
+
+ private Observer getObserver() {
+ return new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addTextToTv("onSubscribe:"+d.isDisposed());
+
+
+ }
+
+ @Override
+ public void onNext(String s) {
+ addTextToTv("onNext:"+ s);
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ addTextToTv("onError "+e.getMessage());
+
+ }
+
+ @Override
+ public void onComplete() {
+ addTextToTv("onComplete");
+
+ }
+ };
+ }
+
+ private void addTextToTv(String s) {
+ tv.append(s);
+ tv.append("\n");
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/ConcurrencyWithSchedulersDemoFragment.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/ConcurrencyWithSchedulersDemoFragment.java
new file mode 100644
index 0000000..3014f86
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/ConcurrencyWithSchedulersDemoFragment.java
@@ -0,0 +1,149 @@
+package com.example.leakdemo.fragments;
+
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.Nullable;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+
+import com.example.leakdemo.R;
+import com.example.leakdemo.base.BaseFragment;
+import com.example.leakdemo.wiring.LogAdapter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.annotations.NonNull;
+import io.reactivex.functions.Function;
+import io.reactivex.observers.DisposableObserver;
+import io.reactivex.schedulers.Schedulers;
+import timber.log.Timber;
+
+
+/**
+ * __ __ _
+ * \ \ / /_ _| |_ _ _ __
+ * \ V / _` | | | | | '_ \
+ * | | (_| | | |_| | | | |
+ * |_|\__,_|_|\__,_|_| |_|
+ * Created by Hades on 2017/7/3.
+ */
+
+public class ConcurrencyWithSchedulersDemoFragment extends BaseFragment {
+
+ @BindView(R.id.pbOperationRunning)
+ ProgressBar pbOperationRunning;
+
+ @BindView(R.id.lstThreadingLog)
+ ListView lstThreadingLog;
+ private LogAdapter adapter;
+ private List logs;
+
+
+ @Override
+ public int layoutResId() {
+ return R.layout.fragment_concurrency_shedulers;
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ setupLogger();
+ }
+
+ @OnClick(R.id.btnStartOp)
+ public void startLongOperation(){
+ setPbVisibility(View.VISIBLE);
+ log("Button Clicked");
+
+ DisposableObserver d = getDisposableObserver();
+ getObservable()
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(d);
+ disposable.add(d);
+
+ }
+
+ private Observable getObservable() {
+ return Observable.just(true)
+ .map(new Function() {
+ @Override
+ public Boolean apply(@NonNull Boolean aBoolean) throws Exception {
+ log("Within Observable");
+ blockCurrentThread();
+ return aBoolean;
+ }
+ });
+ }
+
+ private DisposableObserver getDisposableObserver() {
+ return new DisposableObserver() {
+ @Override
+ public void onNext(Boolean aBoolean) {
+ log(String.format("onNext with return value \"%b\"",aBoolean));
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ Timber.e(e,"Error inRxJav Demo Concurrency");
+ log(String.format("Boo! Error %s",e.getMessage()));
+ setPbVisibility(View.INVISIBLE);
+
+ }
+
+ @Override
+ public void onComplete() {
+ log("On complete");
+ setPbVisibility(View.INVISIBLE);
+
+ }
+ };
+ }
+
+
+ private void blockCurrentThread() {
+ log("block current thread");
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException e) {
+ Timber.d("Operation was inter");
+ }
+ }
+
+ private void setPbVisibility(int visible) {
+ pbOperationRunning.setVisibility(visible);
+ }
+
+ private void setupLogger() {
+ logs=new ArrayList<>();
+ adapter=new LogAdapter(getActivity(),new ArrayList());
+ lstThreadingLog.setAdapter(adapter);
+ }
+
+ private void log(String logMsg){
+ if(isCurrentlyOnMainThread()){
+ logs.add(0,logMsg+" (main thread) ");
+ adapter.clear();
+ adapter.addAll(logs);
+ }else{
+ logs.add(0,logMsg+" (not main thread) ");
+ new Handler(Looper.getMainLooper()).
+ post(new Runnable() {
+ @Override
+ public void run() {
+ adapter.clear();
+ adapter.addAll(logs);
+ }
+ });
+
+ }
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/DebounceFragment.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/DebounceFragment.java
new file mode 100644
index 0000000..ff69132
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/DebounceFragment.java
@@ -0,0 +1,74 @@
+package com.example.leakdemo.fragments;
+
+
+import java.util.concurrent.TimeUnit;
+
+import io.reactivex.Observable;
+import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.Observer;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Created by zhanghehe on 2017/8/13.
+ */
+
+public class DebounceFragment extends Base3Fragment {
+ @Override
+ public void doSomeClick() {
+ getObservable()
+ .debounce(500, TimeUnit.MILLISECONDS)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(getObserver());
+ }
+
+ private Observer super Integer> getObserver() {
+ return new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addText("onSUbscribe"+d.isDisposed());
+ }
+
+ @Override
+ public void onNext(Integer integer) {
+ addText("onNext"+integer);
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ addText("onErrir"+e.getMessage());
+
+ }
+
+ @Override
+ public void onComplete() {
+ addText("onComplete");
+
+ }
+ };
+ }
+
+ private Observable getObservable() {
+ return Observable.create(new ObservableOnSubscribe() {
+ @Override
+ public void subscribe(ObservableEmitter e) throws Exception {
+ e.onNext(1);
+ Thread.sleep(400);
+ e.onNext(2);
+ Thread.sleep(505);
+ e.onNext(3);
+ Thread.sleep(100);
+ e.onNext(4);
+ Thread.sleep(605);
+ e.onNext(5);
+ Thread.sleep(510);
+ e.onComplete();
+
+ }
+ });
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/DebounceSearchEmitterFrament.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/DebounceSearchEmitterFrament.java
new file mode 100644
index 0000000..f0a56da
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/DebounceSearchEmitterFrament.java
@@ -0,0 +1,138 @@
+package com.example.leakdemo.fragments;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.text.TextUtils;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.example.leakdemo.R;
+import com.example.leakdemo.base.BaseFragment;
+import com.example.leakdemo.wiring.LogAdapter;
+import com.jakewharton.rxbinding2.widget.RxTextView;
+import com.jakewharton.rxbinding2.widget.TextViewTextChangeEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import hu.akarnokd.rxjava2.async.DisposableObservable;
+import io.reactivex.Observer;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.functions.Predicate;
+import io.reactivex.observers.DisposableObserver;
+import timber.log.Timber;
+
+/**
+ * __ __ _
+ * \ \ / /_ _| |_ _ _ __
+ * \ V / _` | | | | | '_ \
+ * | | (_| | | |_| | | | |
+ * |_|\__,_|_|\__,_|_| |_|
+ * Created by Hades on 2017/7/4.
+ */
+
+public class DebounceSearchEmitterFrament extends BaseFragment {
+
+ @BindView(R.id.etDebounce)
+ EditText etDebounce;
+
+ @BindView(R.id.ivClear)
+ ImageView ivClear;
+
+ @BindView(R.id.lstThreadingLog)
+ ListView lstThreadingLog;
+ private List logs;
+ private DisposableObserver mDisposable;
+ private LogAdapter adapter;
+
+ @Override
+ public int layoutResId() {
+ return R.layout.fragment_debounce;
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ setupLogger();
+
+ mDisposable = RxTextView.textChangeEvents(etDebounce)
+ .debounce(400, TimeUnit.MILLISECONDS)
+ .filter(new Predicate() {
+ @Override
+ public boolean test(@io.reactivex.annotations.NonNull TextViewTextChangeEvent textViewTextChangeEvent) throws Exception {
+ return TextUtils.isEmpty(textViewTextChangeEvent.text().toString());
+ }
+ }).observeOn(AndroidSchedulers.mainThread())
+ .subscribeWith(getSearchObserver());
+ }
+
+ private void setupLogger() {
+ logs=new ArrayList<>();
+ adapter=new LogAdapter(getActivity(),new ArrayList());
+ lstThreadingLog.setAdapter(adapter);
+ }
+
+ private DisposableObserver getSearchObserver() {
+ return new DisposableObserver() {
+ @Override
+ public void onNext(TextViewTextChangeEvent textViewTextChangeEvent) {
+ log(String.format("Search for %s",textViewTextChangeEvent.text().toString()));
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ Timber.e(e,"------------Woops on error");
+ log("Dang error.Check your logs");
+
+ }
+
+ @Override
+ public void onComplete() {
+ Timber.d("---------------onComplete");
+
+ }
+ };
+ }
+
+ private void log(String logMsg) {
+
+ if (isCurrentlyOnMainThread()) {
+ logs.add(0, logMsg + " (main thread) ");
+ adapter.clear();
+ adapter.addAll(logs);
+ } else {
+ logs.add(0, logMsg + " (NOT main thread) ");
+
+ // You can only do below stuff on main thread.
+ new Handler(Looper.getMainLooper())
+ .post(new Runnable() {
+ @Override
+ public void run() {
+ adapter.clear();
+ adapter.addAll(logs);
+ }
+ }
+
+ );
+ }
+ }
+
+
+ @OnClick(R.id.ivClear)
+ public void onClear() {
+ logs = new ArrayList();
+ adapter.clear();
+ }
+
+
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/DeferExampleFragment.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/DeferExampleFragment.java
new file mode 100644
index 0000000..83ff374
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/DeferExampleFragment.java
@@ -0,0 +1,72 @@
+package com.example.leakdemo.fragments;
+
+
+import android.widget.TextView;
+
+import com.example.leakdemo.R;
+import com.example.leakdemo.model.Car;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import io.reactivex.Observable;
+import io.reactivex.Observer;
+import io.reactivex.disposables.Disposable;
+
+/**
+ * Created by zhanghehe on 2017/8/13.
+ */
+
+public class DeferExampleFragment extends Base2Fragment {
+
+ @BindView(R.id.tv)
+ TextView tv;
+
+ @OnClick(R.id.btn)
+ public void onBtnClick(){
+ Car car=new Car();
+
+ Observable brandDeferObservable=car.brandDeferObservable();
+ car.setBrand("BMW");
+
+ brandDeferObservable.subscribe(
+ getObserver()
+ );
+
+
+ }
+
+ private Observer getObserver(){
+ return new Observer(){
+ @Override
+ public void onSubscribe(Disposable d) {
+ addTextToTv("onSubscribe:"+d.isDisposed());
+
+ }
+
+ @Override
+ public void onNext(String s) {
+ addTextToTv("onNext :"+s);
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ addTextToTv("onError :"+e.getMessage());
+
+ }
+
+ @Override
+ public void onComplete() {
+ addTextToTv("onComplete");
+
+ }
+ };
+ }
+
+ private void addTextToTv(String s) {
+ tv.append(s);
+ tv.append("\n");
+ }
+
+
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/DelayExmapke.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/DelayExmapke.java
new file mode 100644
index 0000000..76d73d9
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/DelayExmapke.java
@@ -0,0 +1,58 @@
+package com.example.leakdemo.fragments;
+
+
+import android.util.Log;
+
+import java.util.concurrent.TimeUnit;
+
+import io.reactivex.Observable;
+import io.reactivex.Observer;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Created by zhanghehe on 2017/8/13.
+ */
+
+public class DelayExmapke extends Base3Fragment{
+ @Override
+ public void doSomeClick() {
+ getObservable().delay(2, TimeUnit.SECONDS)
+ // Run on a background thread
+ .subscribeOn(Schedulers.io())
+ // Be notified on the main thread
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(getObserver());
+
+ }
+
+ private Observable getObservable() {
+ return Observable.just("Amit");
+ }
+
+ private Observer getObserver() {
+ return new Observer() {
+
+ @Override
+ public void onSubscribe(Disposable d) {
+ addText(" onSubscribe : " + d.isDisposed());
+ }
+
+ @Override
+ public void onNext(String value) {
+ addText(" onNext : value : " + value);
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ addText(" onError : " + e.getMessage());
+ }
+
+ @Override
+ public void onComplete() {
+ addText(" onComplete");
+ }
+ };
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/DisposableExample.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/DisposableExample.java
new file mode 100644
index 0000000..f5f6e68
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/DisposableExample.java
@@ -0,0 +1,91 @@
+package com.example.leakdemo.fragments;
+
+
+import android.os.SystemClock;
+import android.util.Log;
+import android.widget.TextView;
+
+import com.example.leakdemo.R;
+
+import java.util.concurrent.Callable;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import io.reactivex.Observable;
+import io.reactivex.ObservableSource;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.observers.DisposableObserver;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * __ __ _
+ * \ \ / /_ _| |_ _ _ __
+ * \ V / _` | | | | | '_ \
+ * | | (_| | | |_| | | | |
+ * |_|\__,_|_|\__,_|_| |_|
+ * Created by Hades on 2017/8/2.
+ */
+
+public class DisposableExample extends Base2Fragment {
+
+ private static final String TAG = DisposableExample.class.getSimpleName();
+ @BindView(R.id.tv)
+ TextView tv;
+
+ private final CompositeDisposable disposables=new CompositeDisposable();
+ @Override
+ public int layoutResId() {
+ return R.layout.fragment_example;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+
+ disposables.clear();
+ }
+
+ @OnClick(R.id.btn)
+ public void onBtnClick(){
+ disposables.add(sampleObservable().subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribeWith(new DisposableObserver() {
+ @Override
+ public void onNext(String s) {
+ tv.append(" onNext : value: "+s);
+ tv.append("\n");
+ Log.d(TAG," onNext value: "+s);
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ tv.append("onError :"+e.getMessage());
+ tv.append("\n");
+ Log.d(TAG," on Error:"+ e.getMessage());
+
+ }
+
+ @Override
+ public void onComplete() {
+ tv.append(" onComplete");
+ tv.append("\n");
+ Log.d(TAG,"onComplete");
+
+ }
+ }));
+
+
+ }
+
+ private Observable sampleObservable() {
+ return Observable.defer(new Callable>() {
+ @Override
+ public ObservableSource extends String> call() throws Exception {
+ SystemClock.sleep(2000);
+ return Observable.just("one","two","three","four","five");
+ }
+ });
+ }
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/DistinctExampleFragment.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/DistinctExampleFragment.java
new file mode 100644
index 0000000..9ebd070
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/DistinctExampleFragment.java
@@ -0,0 +1,69 @@
+package com.example.leakdemo.fragments;
+
+
+import android.widget.TextView;
+
+import com.example.leakdemo.R;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import io.reactivex.Observable;
+import io.reactivex.Observer;
+import io.reactivex.disposables.Disposable;
+
+/**
+ * Created by zhanghehe on 2017/8/13.
+ */
+
+public class DistinctExampleFragment extends Base2Fragment{
+
+
+ @BindView(R.id.tv)
+ TextView tv;
+ @OnClick(R.id.btn)
+ public void onBtnClick(){
+ getObservable()
+ .distinct()
+ .subscribe(getObserver());
+ }
+
+ private Observer super Integer> getObserver() {
+ return new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addText("onSubscribe"+d.isDisposed());
+
+ }
+
+ @Override
+ public void onNext(Integer integer) {
+ addText("onNext:"+integer);
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ addText("onError"+e.getMessage());
+
+ }
+
+ @Override
+ public void onComplete() {
+ addText("onComplete");
+
+ }
+ };
+ }
+
+ private void addText(String s) {
+ tv.append(s);
+ tv.append("\n");
+ }
+
+ private Observable getObservable() {
+ return Observable.just(1,2,1,1,2,3,4,5,6);
+
+ }
+
+
+}
diff --git a/leakdemo/src/main/java/com/example/leakdemo/fragments/ExponentialBackOffFragment.java b/leakdemo/src/main/java/com/example/leakdemo/fragments/ExponentialBackOffFragment.java
new file mode 100644
index 0000000..6dd6532
--- /dev/null
+++ b/leakdemo/src/main/java/com/example/leakdemo/fragments/ExponentialBackOffFragment.java
@@ -0,0 +1,193 @@
+package com.example.leakdemo.fragments;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.widget.ListView;
+
+import com.example.leakdemo.R;
+import com.example.leakdemo.base.BaseFragment;
+import com.example.leakdemo.wiring.LogAdapter;
+
+import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscription;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import hu.akarnokd.rxjava2.math.MathFlowable;
+import io.reactivex.Flowable;
+import io.reactivex.annotations.NonNull;
+import io.reactivex.functions.Consumer;
+import io.reactivex.functions.Function;
+import io.reactivex.subscribers.DisposableSubscriber;
+import timber.log.Timber;
+
+/**
+ * Created by zhanghehe on 2017/7/18.
+ */
+
+public class ExponentialBackOffFragment extends BaseFragment {
+
+ @BindView(R.id.lstThreadingLog)
+ ListView logList;
+ private ArrayList logs;
+ private LogAdapter adapter;
+
+ @Override
+ public int layoutResId() {
+ return R.layout.fragment_exponential_back;
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ setupLogger();
+ }
+
+ private void setupLogger() {
+ logs=new ArrayList();
+ adapter=new LogAdapter(getActivity(),new ArrayList());
+ logList.setAdapter(adapter);
+
+ }
+
+ @OnClick(R.id.btnExBackoffRetry)
+ public void startRetryWithExponentialBackoffStategy(){
+ logs=new ArrayList();
+
+ adapter.clear();
+
+ DisposableSubscriber