Skip to content

Commit

Permalink
增加可自定进行订阅注销的RxLifecycle
Browse files Browse the repository at this point in the history
xuexiangjys committed Jun 11, 2018
1 parent 05a4cd0 commit 498c4d5
Showing 13 changed files with 659 additions and 14 deletions.
6 changes: 6 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -24,6 +24,12 @@ dependencies {
//butterknife的sdk
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

implementation 'io.reactivex.rxjava2:rxjava:2.1.12'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
//rxbinding的sdk
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'

implementation project(':rxutil2')

implementation 'com.github.xuexiangjys.XUtil:xutil-core:1.1.3'
Original file line number Diff line number Diff line change
@@ -30,7 +30,6 @@

import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Consumer;
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
import android.widget.Button;
import android.widget.Toast;

import com.xuexiang.rxutil2.lifecycle.RxLifecycle;
import com.xuexiang.rxutil2.logs.RxLog;
import com.xuexiang.rxutil2.rxjava.DisposablePool;
import com.xuexiang.rxutil2.rxjava.RxJavaUtils;
@@ -44,6 +45,7 @@

/**
* RxJavaUtils演示示例
*
* @author xuexiang
* @date 2018/3/8 下午3:37
*/
@@ -72,7 +74,7 @@ protected void initListener() {

@OnClick({R.id.btn_do_in_io, R.id.btn_do_in_ui, R.id.btn_do_in_io_ui, R.id.btn_loading, R.id.btn_polling, R.id.btn_count_down, R.id.btn_foreach})
void OnClick(View v) {
switch(v.getId()) {
switch (v.getId()) {
case R.id.btn_do_in_io:
RxJavaUtils.doInIOThread(new RxIOTask<String>("我是入参123") {
@Override
@@ -125,12 +127,14 @@ public void onNext(String s) {
});
break;
case R.id.btn_polling:
DisposablePool.get().add(RxJavaUtils.polling(5, new Consumer<Long>() {
@Override
public void accept(Long o) throws Exception {
Toast.makeText(RxJavaActivity.this, "正在监听", Toast.LENGTH_SHORT).show();
}
}), "polling");
RxJavaUtils.polling(5)
.compose(RxLifecycle.with(this).<Long>bindToLifecycle())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long o) throws Exception {
toast("正在监听:" + o);
}
});
break;
case R.id.btn_count_down:
DisposablePool.get().add(RxJavaUtils.countDown(30, new SimpleSubscriber<Long>() {
@@ -139,17 +143,19 @@ public void onStart() {
super.onStart();
mBtnCountDown.setEnabled(false);
}

@Override
public void onNext(Long aLong) {
mBtnCountDown.setText(String.format("%s s后重新获取", aLong));
}

@Override
public void onComplete() {
super.onComplete();
mBtnCountDown.setText("重新获取");
mBtnCountDown.setEnabled(true);
}
}),"countDown");
}), "countDown");

break;
case R.id.btn_foreach:
@@ -172,6 +178,7 @@ public Integer doInIOThread(String s) {
RxLog.e("[doInIOThread]" + getLooperStatus() + ", 入参:" + s);
return Integer.parseInt(s);
}

@Override
public void doInUIThread(Integer integer) {
RxLog.e("[doInUIThread] " + getLooperStatus() + ", 入参:" + integer);
@@ -186,6 +193,7 @@ public void doInUIThread(Integer integer) {

/**
* 获取当前线程的状态
*
* @return
*/
public String getLooperStatus() {
@@ -195,7 +203,6 @@ public String getLooperStatus() {

@Override
protected void onDestroy() {
DisposablePool.get().remove("polling");
DisposablePool.get().remove("countDown");
super.onDestroy();
}
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@
import android.widget.Toast;

import com.squareup.leakcanary.RefWatcher;
import com.xuexiang.rxutil2.lifecycle.RxLifecycle;
import com.xuexiang.rxutil2demo.App;

import butterknife.ButterKnife;
@@ -42,6 +43,7 @@ public abstract class BaseActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
RxLifecycle.injectRxLifecycle(this);
mUnbinder = ButterKnife.bind(this);
initArgs();
initViews();
8 changes: 4 additions & 4 deletions rxutil2/build.gradle
Original file line number Diff line number Diff line change
@@ -14,12 +14,12 @@ android {
}

dependencies {
implementation 'com.android.support:appcompat-v7:26.1.0'
api 'io.reactivex.rxjava2:rxjava:2.1.12'
api 'io.reactivex.rxjava2:rxandroid:2.0.2'
compileOnly 'com.android.support:appcompat-v7:26.1.0'
compileOnly 'io.reactivex.rxjava2:rxjava:2.1.12'
compileOnly 'io.reactivex.rxjava2:rxandroid:2.0.2'

//rxbinding的sdk
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
compileOnly 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}

apply from: "https://raw.githubusercontent.com/xuexiangjys/XUtil/master/JitPackUpload.gradle"
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.xuexiang.rxutil2.lifecycle;

/**
* Activity的生命周期
*
* @author xuexiang
* @since 2018/6/11 上午12:45
*/
public enum ActivityLifecycle {
onCreate,
onStart,
onResume,
onPause,
onStop,
onDestroy,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.xuexiang.rxutil2.lifecycle;

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;

/**
* 应用的生命周期
*
* @author xuexiang
* @since 2018/6/11 上午1:09
*/
final class ActivityRxLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
RxLifecycle.injectRxLifecycle(activity);
}

@Override
public void onActivityStarted(Activity activity) {

}

@Override
public void onActivityResumed(Activity activity) {

}

@Override
public void onActivityPaused(Activity activity) {

}

@Override
public void onActivityStopped(Activity activity) {

}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

}

@Override
public void onActivityDestroyed(Activity activity) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.xuexiang.rxutil2.lifecycle;

import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;

import io.reactivex.Observable;
import io.reactivex.subjects.BehaviorSubject;


/**
* 用于添加到Activity中的Fragment,使得和activity的生命周期同步,从而间接绑定了activity的生命周期
*
* @author xuexiang
* @since 2018/6/11 上午12:58
*/
public class LifecycleFragment extends Fragment implements LifecycleManager {
private final BehaviorSubject<ActivityLifecycle> mLifecycleSubject;

public LifecycleFragment() {
mLifecycleSubject = BehaviorSubject.create();
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
mLifecycleSubject.onNext(ActivityLifecycle.onCreate);
super.onCreate(savedInstanceState);
}

@Override
public void onStart() {
mLifecycleSubject.onNext(ActivityLifecycle.onStart);
super.onStart();
}

@Override
public void onResume() {
mLifecycleSubject.onNext(ActivityLifecycle.onResume);
super.onResume();
}

@Override
public void onPause() {
mLifecycleSubject.onNext(ActivityLifecycle.onPause);
super.onPause();
}

@Override
public void onStop() {
mLifecycleSubject.onNext(ActivityLifecycle.onStop);
super.onStop();
}

@Override
public void onDestroy() {
mLifecycleSubject.onNext(ActivityLifecycle.onDestroy);
super.onDestroy();
}

@Override
public Observable<ActivityLifecycle> getActivityLifecycle() {
return mLifecycleSubject;
}

@Override
public <T> LifecycleTransformer<T> bindToActivityLifecycle(final ActivityLifecycle activityLifecycle) {
return new LifecycleTransformer<>(mLifecycleSubject, activityLifecycle);
}

@Override
public <T> LifecycleTransformer<T> bindToLifecycle() {
return new LifecycleTransformer<>(mLifecycleSubject);
}

@Override
public <T> LifecycleTransformer<T> bindOnDestroy() {
return bindToActivityLifecycle(ActivityLifecycle.onDestroy);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.xuexiang.rxutil2.lifecycle;

import io.reactivex.Observable;

/**
* 生命周期管理者,绑定生命周期
*
* @author xuexiang
* @since 2018/6/11 上午12:49
*/
public interface LifecycleManager {

/**
* 获取Activity绑定的生命周期
* @return
*/
Observable<ActivityLifecycle> getActivityLifecycle();

/**
* 绑定到特定的Activity生命周期进行订阅注销
* @param activityLifecycle
* @param <T>
* @return
*/
<T> LifecycleTransformer<T> bindToActivityLifecycle(ActivityLifecycle activityLifecycle);

/**
* 自动绑定Activity生命周期进行订阅注销
* @param <T>
* @return
*/
<T> LifecycleTransformer<T> bindToLifecycle();

/**
* 绑定到Activity的OnDestroy进行订阅注销
* @param <T>
* @return
*/
<T> LifecycleTransformer<T> bindOnDestroy();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package com.xuexiang.rxutil2.lifecycle;

import org.reactivestreams.Publisher;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Completable;
import io.reactivex.CompletableSource;
import io.reactivex.CompletableTransformer;
import io.reactivex.Flowable;
import io.reactivex.FlowableTransformer;
import io.reactivex.Maybe;
import io.reactivex.MaybeSource;
import io.reactivex.MaybeTransformer;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.SingleTransformer;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;

import static com.xuexiang.rxutil2.lifecycle.ActivityLifecycle.onDestroy;
import static com.xuexiang.rxutil2.lifecycle.ActivityLifecycle.onPause;
import static com.xuexiang.rxutil2.lifecycle.ActivityLifecycle.onStop;

/**
* 生命周期转化器
*
* @author xuexiang
* @since 2018/6/11 上午12:50
*/
public class LifecycleTransformer<T> implements ObservableTransformer<T, T>, FlowableTransformer<T, T>, SingleTransformer<T, T>, MaybeTransformer<T, T>, CompletableTransformer {
private Observable<?> mObservable;


LifecycleTransformer(Observable<ActivityLifecycle> lifecycleObservable) {
Observable<ActivityLifecycle> observable = lifecycleObservable.share();
mObservable = Observable.combineLatest(observable.take(1).map(ACTIVITY_LIFECYCLE), observable.skip(1),
new BiFunction<ActivityLifecycle, ActivityLifecycle, Boolean>() {
@Override
public Boolean apply(@NonNull ActivityLifecycle ActivityLifecycle, @NonNull ActivityLifecycle ActivityLifecycle2) throws Exception {
return ActivityLifecycle.equals(ActivityLifecycle2);
}
})
.filter(new Predicate<Boolean>() {
@Override
public boolean test(@NonNull Boolean aBoolean) throws Exception {
return aBoolean;
}
});

}

LifecycleTransformer(Observable<ActivityLifecycle> lifecycleObservable, final ActivityLifecycle ActivityLifecycle) {
mObservable = lifecycleObservable
.filter(new Predicate<ActivityLifecycle>() {
@Override
public boolean test(@NonNull ActivityLifecycle event) throws Exception {
return event.equals(ActivityLifecycle);
}
})
.take(1);
}

@Override
public ObservableSource<T> apply(Observable<T> upstream) {
return upstream.takeUntil(mObservable);
}

@Override
public Publisher<T> apply(Flowable<T> upstream) {
return upstream.takeUntil(mObservable.toFlowable(BackpressureStrategy.LATEST));
}

@Override
public SingleSource<T> apply(Single<T> upstream) {
return upstream.takeUntil(mObservable.firstOrError());
}

@Override
public MaybeSource<T> apply(Maybe<T> upstream) {
return upstream.takeUntil(mObservable.firstElement());
}

@Override
public CompletableSource apply(Completable upstream) {
return Completable.ambArray(upstream);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

LifecycleTransformer<?> that = (LifecycleTransformer<?>) o;

return mObservable.equals(that.mObservable);
}

@Override
public int hashCode() {
return mObservable.hashCode();
}

@Override
public String toString() {
return "LifecycleTransformer{" +
"mObservable=" + mObservable +
'}';
}


// Figures out which corresponding next lifecycle event in which to unsubscribe, for Activities
private static final Function<ActivityLifecycle, ActivityLifecycle> ACTIVITY_LIFECYCLE =
new Function<ActivityLifecycle, ActivityLifecycle>() {
@Override
public ActivityLifecycle apply(@NonNull ActivityLifecycle lastEvent) throws Exception {
switch (lastEvent) {
case onCreate:
return onDestroy;
case onStart:
return onStop;
case onResume:
return onPause;
case onPause:
return onStop;
case onStop:
return onDestroy;
case onDestroy:
throw new IllegalStateException("Cannot injectRxLifecycle to Activity lifecycle when outside of it.");
default:
throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
}
}
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.xuexiang.rxutil2.lifecycle;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;

import io.reactivex.Observable;
import io.reactivex.subjects.BehaviorSubject;


/**
* 用于添加到Activity中的Fragment,使得和activity的生命周期同步,从而间接绑定了activity的生命周期
*
* @author xuexiang
* @since 2018/6/11 上午1:01
*/
public class LifecycleV4Fragment extends Fragment implements LifecycleManager {
private final BehaviorSubject<ActivityLifecycle> mLifecycleSubject;

public LifecycleV4Fragment() {
mLifecycleSubject = BehaviorSubject.create();
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
mLifecycleSubject.onNext(ActivityLifecycle.onCreate);
super.onCreate(savedInstanceState);
}

@Override
public void onStart() {
mLifecycleSubject.onNext(ActivityLifecycle.onStart);
super.onStart();
}

@Override
public void onResume() {
mLifecycleSubject.onNext(ActivityLifecycle.onResume);
super.onResume();
}

@Override
public void onPause() {
mLifecycleSubject.onNext(ActivityLifecycle.onPause);
super.onPause();
}

@Override
public void onStop() {
mLifecycleSubject.onNext(ActivityLifecycle.onStop);
super.onStop();
}

@Override
public void onDestroy() {
mLifecycleSubject.onNext(ActivityLifecycle.onDestroy);
super.onDestroy();
}

@Override
public Observable<ActivityLifecycle> getActivityLifecycle() {
return mLifecycleSubject;
}

@Override
public <T> LifecycleTransformer<T> bindToActivityLifecycle(final ActivityLifecycle activityLifecycle) {
return new LifecycleTransformer<>(mLifecycleSubject, activityLifecycle);
}

@Override
public <T> LifecycleTransformer<T> bindToLifecycle() {
return new LifecycleTransformer<>(mLifecycleSubject);
}

@Override
public <T> LifecycleTransformer<T> bindOnDestroy() {
return bindToActivityLifecycle(ActivityLifecycle.onDestroy);
}
}
180 changes: 180 additions & 0 deletions rxutil2/src/main/java/com/xuexiang/rxutil2/lifecycle/RxLifecycle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package com.xuexiang.rxutil2.lifecycle;

import android.app.Activity;
import android.app.Application;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import java.lang.reflect.Field;

/**
* RxLifecycle,自动绑定到Activity的生命周期中,自动进行订阅的注销
*
* @author xuexiang
* @since 2018/6/11 上午1:07
*/
public final class RxLifecycle {

private static final String FRAGMENT_TAG = "rx_lifecycle_tag";

private RxLifecycle() {
throw new UnsupportedOperationException("u can't instantiate me...");
}

//=========================注入并绑定Activity的生命周期================================//

/**
* 注入并绑定Activity的生命周期<br>
* use in {@link Activity} onCreate
* <pre> {@code
* public class BaseActivity extends AppCompatActivity {
* protected void onCreate(Bundle savedInstanceState) {
* super.onCreate(savedInstanceState);
* RxLifecycle.injectRxLifecycle(this);
* }
* }
* }</pre>
*
* @param activity
*/
public static void injectRxLifecycle(Activity activity) {
with(activity);
}

/**
* 注入并绑定Activity的生命周期<br>
*
* @param object
*/
private static void injectRxLifecycle(Object object) {
if (object instanceof View) {
with((View) object);
} else {
with(object);
}
}

/**
* 注入并绑定Activity的生命周期<br>
* <p>
* use in {@link Application} oncreate
* <pre> {@code
* public class RxLifecycleAPP extends Application {
* public void onCreate() {
* super.onCreate();
* RxLifecycle.injectRxLifecycle(this);
* }
* }
* }</pre>
*
* @param application
*/
public static void injectRxLifecycle(Application application) {
application.registerActivityLifecycleCallbacks(new ActivityRxLifecycleCallbacks());
}

//===========================获得生命周期绑定管理者,进行生命周期的绑定==============================//

/**
* 获得生命周期绑定管理者,进行生命周期的绑定
*
* @param activity
* @return
*/
public static LifecycleManager with(Activity activity) {
if (activity instanceof FragmentActivity) {
return with((FragmentActivity) activity);
}
FragmentManager fm = activity.getFragmentManager();
Fragment fragment = fm.findFragmentByTag(FRAGMENT_TAG);
if (fragment == null) {
fragment = new LifecycleFragment();
fm.beginTransaction().add(fragment, FRAGMENT_TAG).commitAllowingStateLoss();
fm.executePendingTransactions();
}
return (LifecycleManager) fragment;
}

/**
* 获得生命周期绑定管理者,进行生命周期的绑定
*
* @param activity
* @return
*/
private static LifecycleManager with(FragmentActivity activity) {
android.support.v4.app.FragmentManager fm = activity.getSupportFragmentManager();
android.support.v4.app.Fragment fragment = fm.findFragmentByTag(FRAGMENT_TAG);
if (fragment == null) {
fragment = new LifecycleV4Fragment();
fm.beginTransaction().add(fragment, FRAGMENT_TAG).commitNowAllowingStateLoss();
}

return (LifecycleManager) fragment;
}

/**
* 获得生命周期绑定管理者,进行生命周期的绑定
*
* @param fragment
* @return
*/
public static LifecycleManager with(Fragment fragment) {
return with(fragment.getActivity());
}

/**
* 获得生命周期绑定管理者,进行生命周期的绑定
*
* @param fragment
* @return
*/
public static LifecycleManager with(android.support.v4.app.Fragment fragment) {
return with(fragment.getActivity());
}

/**
* 获得生命周期绑定管理者,进行生命周期的绑定
*
* @param context ensure context can be cast {@link Activity}
*/
public static LifecycleManager with(Context context) {
if (context instanceof AppCompatActivity) {
return with((FragmentActivity) context);
}
if (context instanceof Activity) {
return with((Activity) context);
}
if (context instanceof ContextWrapper) {
return with(((ContextWrapper) context).getBaseContext());
}
throw new ClassCastException(context.getClass().getSimpleName() + " can\'t cast Activity !");
}

public static LifecycleManager with(View view) {
return with(view.getContext());
}

private static LifecycleManager with(Object object) {
if (object instanceof Context) {
return with((Context) object);
}
for (Field field : object.getClass().getDeclaredFields()) {
try {
field.setAccessible(true);
Object value = field.get(object);
if (value instanceof Context) {
return with((Context) value);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
throw new ClassCastException(object.getClass().getSimpleName() + " can\'t convert Context !");
}

}
45 changes: 45 additions & 0 deletions rxutil2/src/main/java/com/xuexiang/rxutil2/rxjava/RxJavaUtils.java
Original file line number Diff line number Diff line change
@@ -116,6 +116,15 @@ public void accept(RxIOTask<T> rxIOTask) throws Exception {
}
//========================轮询操作==========================//

/**
* 轮询操作
*
* @param interval 轮询间期
*/
public static Flowable<Long> polling(long interval) {
return polling(0, interval, TimeUnit.SECONDS);
}

/**
* 轮询操作
*
@@ -137,6 +146,18 @@ public static Disposable polling(long initialDelay, long interval, @NonNull Cons
return polling(initialDelay, interval, TimeUnit.SECONDS, consumer, new SimpleThrowableAction(TAG));
}

/**
* 轮询操作
*
* @param initialDelay 初始延迟
* @param interval 轮询间期
* @param unit 轮询间期时间单位
*/
public static Flowable<Long> polling(long initialDelay, long interval, @NonNull TimeUnit unit) {
return Flowable.interval(initialDelay, interval, unit)
.observeOn(AndroidSchedulers.mainThread());
}

/**
* 轮询操作
*
@@ -221,6 +242,17 @@ public static Disposable delay(@NonNull long delayTime, @NonNull TimeUnit unit,
.subscribe(consumer, errorConsumer);
}

/**
* 延迟操作
*
* @param delayTime 延迟时间
* @param unit 延迟时间单位
*/
public static Observable<Long> delay(long delayTime, @NonNull TimeUnit unit) {
return Observable.timer(delayTime, unit)
.observeOn(AndroidSchedulers.mainThread());
}

/**
* 延迟操作
*
@@ -234,6 +266,19 @@ public static Disposable delay(long delayTime, @NonNull TimeUnit unit, @NonNull
.subscribeWith(subscriber);
}

/**
* 延迟操作
*
* @param t 发射源
* @param delayTime 延迟时间
* @param unit 延迟时间单位
*/
public static <T> Observable<T> delay(@NonNull T t, long delayTime, @NonNull TimeUnit unit) {
return Observable.just(t)
.delay(delayTime, unit)
.observeOn(AndroidSchedulers.mainThread());
}

/**
* 延迟操作
*

0 comments on commit 498c4d5

Please sign in to comment.