(轉)動手實現一個輕量級無侵入性的RxJava自動登出庫RxLifecycle
*本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出
一. 概述
RxLifecycle是一個輕量級,侵入性低的RxJava登出管理庫.他不會改變原有專案Activity的繼承結構,輕鬆實現RxJava在Android平臺下的自動登出,甚至你在自定義view的時候使用RxJava都能輕鬆完整自動登出功能.如果你的專案在開發中期想要引入RxJava相關的自動登出庫,這個庫將是你不錯的選擇,原因就在他的入侵性低.
專案地址: 歡迎star
https://github.com/dhhAndroid/RxLifecycle
gradle 依賴:
compile ‘com.dhh:rxlifecycle:1.5’
二. 使用方法(請檢視github主頁,因為版本迭代,使用方法有所不同)
把RxLifecycle注入到Activity,請放心,RxLifecycle庫並不會引用with()傳進去的上下文引用,所以不用反登出,不會造成記憶體洩漏,這塊的邏輯類似Glide的處理方式,在原理解析部分會講到.以下兩種注入方式,實現一種即可:
如果你有一個BaseActivity,僅需在BaseActivity的onCreate方法裡注入RxLifecycle:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); RxLifecycle.injectRxLifecycle(this); }
既然你有一個BaseActivity,可以將RxLifecycle程式碼封裝一下:
private <T> LifecycleTransformer<T> bindToLifecycle() { return RxLifecycle.with(this).bindToLifecycle(); } private <T> LifecycleTransformer<T> bindOnDestroy() { return RxLifecycle.with(this).bindOnDestroy(); } private <T> LifecycleTransformer<T> bindUntilEvent(ActivityEvent event) { return RxLifecycle.with(this).bindUntilEvent(event); } //use @Override protected void onStart() { super.onStart(); Observable.just(1) //use .compose(bindToLifecycle()) .subscribe(); }
或者你已經有了繼承Application的操作,你也可以這樣注入RxLifecycle:
public class RxLifecycleAPP extends Application {
@Override
public void onCreate() {
super.onCreate();
RxLifecycle.injectRxLifecycle(this);
}
}
注意:
1. 以上兩種注入RxLifecycle的方式,實現一種就可以了,同時實現也沒有問題,如果你樂意!
2. 如果你不在Activity的”onPause”生命週期及其以後的生命週期裡訂閱一個Observable,注入RxLifecycle的步驟可以省略不做.如果在Activity的”onPause”生命週期及其以後的生命週期裡訂閱一個Observable,並且使用RxLifecycle.with(this).bindToLifecycle(),必須進行RxLifecycle注入步奏.在原理解析部分會說明導致這種問題的原因.程式碼示例: @Override
protected void onPause() {
super.onPause();
Observable.just("dhhAndroid")
//其他方式繫結不用預先注入
.compose(RxLifecycle.with(this).<String>bindOnDestroy())
.subscribe();
Observable.just(1)
//在onPause及其以後生命週期,使用bindToLifecycle()必須先注入RxLifecycle
.compose(RxLifecycle.with(this).<Integer>bindToLifecycle())
.subscribe();
}
3. 為了簡化和保險,可以忽略第二條,全部注入,第二條就當我在瞎BB……
在Activity和Fragment中使用:
僅僅需要在你原先的Observable事件流上用compose操作符加上如下程式碼:
Observable.timer(10, TimeUnit.SECONDS)
//自動判斷生命週期
.compose(RxLifecycle.with(this).<Long>bindToLifecycle())
.subscribe();
Observable.timer(10, TimeUnit.SECONDS)
//當activity onStop 登出
.compose(RxLifecycle.with(this).<Long>bindUntilEvent(ActivityEvent.onStop))
.subscribe();
Observable.just("dhhAndroid")
//當activity onDestroy 登出
.compose(RxLifecycle.with(this).<String>bindOnDestroy())
.subscribe();
RxLifecycle.with(),with方法可以接收的引數型別有Activity,Context(說明:這個Context必須能強轉成Activity),View,Fragment,V4.Fragment等.
在自定義view用使用
如果你在自定義view的時候裡面使用的RxJava,以及View內部有retrofit+RxJava的網路訪問,已經RxJava操作的耗時資料轉換,同樣支援一行程式碼管理RxJava自動登出.用法和在activity和fragment裡一樣:
public class MyView extends View {
//other...
public void doSomething(){
Observable.timer(10, TimeUnit.SECONDS)
//自動判斷生命週期
.compose(RxLifecycle.with(this).<Long>bindToLifecycle())
.subscribe();
Observable.timer(10, TimeUnit.SECONDS)
//當activity onStop 登出
.compose(RxLifecycle.with(this).<Long>bindUntilEvent(ActivityEvent.onStop))
.subscribe();
Observable.just("dhhAndroid")
//當activity onDestroy 登出
.compose(RxLifecycle.with(this).<String>bindOnDestroy())
.subscribe();
....
}
}
在其他層使用
在MVP架構或者其他地方使用RxLifecycle時,僅需確保所使用的地方能獲取到一個能轉化成Activity的Context即可. 專案裡我寫了一個with過載方法可傳入任意物件,只要能轉化成Context,或者通過反射能獲取到所傳物件的成員變數有能轉化成Context(Activity),也可實現RxJava生命週期自動繫結,但考慮到效能問題暫未開放(private方法).你可以根據這用思路,結合自己專案進行擴充套件.程式碼如下:
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 !");
}
三 . 原理解析(開始秀操作了,別打我)
首先聊一下寫這個庫的初衷,首先RxJava的確是一個優秀的非同步操作庫,這也就導致了在Android平臺上使用時,記憶體洩漏的問題.所以要在適當的時候(一般是RxJava程式碼依託的Activity檢視onDestroy的時候),登出掉Observable的事件任務.那麼我們先聊聊RxJava的登出都有那些方式,以及什麼條件能觸發登出.
1.生成Subscription,在Activity的onDestroy時登出:
private Subscription mSubscription;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mSubscription = Observable.just(1).subscribe();
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mSubscription!=null&&!mSubscription.isUnsubscribed()) {
mSubscription.unsubscribe();
}
}
這中方式算是傳統方式,比較笨重,如果介面中有多個網路請求,或者RxBus接收資料的話,這樣登出太累了.
2. 條件觸發,取消訂閱關係,取消Observable事件流任務.
這裡麵條件觸發的就很多了,比如take系列的操作符,都是在滿足條件的時候開始訂閱,或者取消訂閱. 以及在 subscriber的onNext()方法中滿足某些條件都能取消訂閱,還有一個另類的方法,就是是Observable的事件流執行過程中拋異常,也可以達到登出的目的,例項程式碼:
Observable.just(1, 23, 434, 5454, 343, 346, 56, 67, 4, -1)
//取前五個就登出
.take(5)
//直到條件滿足,登出
.takeUntil(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer > 66666;
}
})
//直到另外一個Observable傳送資料就登出,本庫主要用的這個操作符
.takeUntil(Observable.just(1))
.first(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer == 111;
}
})
.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
if (integer < 0) {
//拋異常登出,這種用法在我另外一個庫RxProgressManager使用到
throw new RuntimeException("資料不能小於0");
}
return integer;
}
})
.subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
if (integer == 666) {
//當滿足條件登出
unsubscribe();
}
}
});
本庫主要利用takeUntil(otherObservable)實現,takeUntil操作符演示圖:
一旦otherObservable傳送資料原Observable就取消訂閱.所以我們要做的就是將Activity的生命週期資訊通過Observable包裝成otherObservable,然後跟隨生命週期傳送資訊,到達到我們需要的生命週期的時候(比如onDestroy)取消訂閱.幸好RxJava已經為我們實現了這種功能的Subject,Subject extends Observable implement Observer,是一種Observable與 subscriber之間的橋樑:
public abstract class Subject<T, R> extends Observable<R> implements Observer<T> {
protected Subject(OnSubscribe<R> onSubscribe) {
super(onSubscribe);
}
public abstract boolean hasObservers(); public final SerializedSubject<T, R> toSerialized() {
if (getClass() == SerializedSubject.class) {
return (SerializedSubject<T, R>)this;
}
return new SerializedSubject<T, R>(this);
}
}
RxJava已經預設實現了幾種XXXSubject,其他的我就不介紹了,只介紹本文要用到的 BehaviorSubject ,他的特點是當有subscriber訂閱BehaviorSubject時,BehaviorSubject都將這個subscriber訂閱之前發射的最後一個數據一併發給他,如果BehaviorSubject已經執行onCompleted或者onError,那麼將會把onCompleted或者onError通知傳送給這個Subscriber.
// observer will receive all 4 events (including "default").
BehaviorSubject<Object> subject = BehaviorSubject.create("default");
subject.subscribe(observer);
subject.onNext("one");
subject.onNext("two");
subject.onNext("three");
// observer will receive the "one", "two" and "three" events, but not "default" and "zero"
BehaviorSubject<Object> subject = BehaviorSubject.create("default");
subject.onNext("zero");
subject.onNext("one");
subject.subscribe(observer);
subject.onNext("two");
subject.onNext("three");
// observer will receive only onCompleted
BehaviorSubject<Object> subject = BehaviorSubject.create("default");
subject.onNext("zero");
subject.onNext("one");
subject.onCompleted();
subject.subscribe(observer);
// observer will receive only onError
BehaviorSubject<Object> subject = BehaviorSubject.create("default");
subject.onNext("zero");
subject.onNext("one");
subject.onError(new RuntimeException("error"));
subject.subscribe(observer);
那麼我們在Activity或Fragment中就可以這樣(由於Fragment依託於Activity,我在本專案裡,Fragment的生命週期認為是和Activity一樣的,沒有處理Fragment比Activity多的生命週期回撥):
public class MainActivity extends AppCompatActivity {
private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
lifecycleSubject.onNext(ActivityEvent.onCreate);
super.onCreate(savedInstanceState);
Observable.just(1)
.takeUntil(lifecycleSubject.first(new Func1<ActivityEvent, Boolean>() {
@Override
public Boolean call(ActivityEvent event) {
return event==ActivityEvent.onDestory;
}
}))
.subscribe();
}
@Override
public void onStart() {
lifecycleSubject.onNext(ActivityEvent.onStart);
super.onStart();
}
@Override
public void onResume() {
lifecycleSubject.onNext(ActivityEvent.onResume);
super.onResume();
}
@Override
public void onPause() {
lifecycleSubject.onNext(ActivityEvent.onPause);
super.onPause();
}
@Override
public void onStop() {
lifecycleSubject.onNext(ActivityEvent.onStop);
super.onStop();
}
@Override
public void onDestroy() {
lifecycleSubject.onNext(ActivityEvent.onDestory);
super.onDestroy();
}
}
ActivityEvent是一個列舉,列舉出了Activity的生命週期:
public enum ActivityEvent {
onCreate,
onStart,
onResume,
onPause,
onStop,
onDestory,
}
這樣我們通過lifecycleSubject將Activity的生命週期一一發出,用takeUntil將其作為otherObservable連線到原Observable上,在通過first操作符,直到接收到我們指定的生命週期(上面指定的是onDestroy),原Observable若沒登出,就會登出.first操作符演示圖如下(和takeFirst操作符類似):
這樣我們已經完成了通過Activity生命週期登出RxJava的核心原理,那麼我們是不是可以將這個固定操作封裝成我們自己的操作符?當然是可以了, RxJava提供了兩種自定義操作符型別,一種是Observable.Operator,通過lift()操作符將自定義操作符連線到Observable上,這種操作符是對資料做轉換的,不適用我們的應用場景,我們是要對Observable做變換,我們需要使用第二種自定義操作符Observable.Transformer,它是對上游的Observable做變換:
public class LifecycleTransformer<T> implements Observable.Transformer<T, T> {
private Observable<ActivityEvent> lifecycleObservable;
private ActivityEvent activityEvent;
LifecycleTransformer(Observable<ActivityEvent> lifecycleObservable, ActivityEvent activityEvent) {
this.lifecycleObservable = lifecycleObservable;
this.activityEvent = activityEvent;
}
@Override
public Observable<T> call(Observable<T> sourceObservable) {
return sourceObservable.takeUntil(getLifecycleObservable());
}
@NonNull
private Observable<?> getLifecycleObservable() {
lifecycleObservable.takeFirst(new Func1<ActivityEvent, Boolean>() {
@Override
public Boolean call(ActivityEvent event) {
return activityEvent == event;
}
});
}
}
這個時候我們就可以使用 compose操作符將我們自定義的LifecycleTransformer連線到原來的Observable上:
Observable.just(1)
.compose(new LifecycleTransformer<Integer>(lifecycleSubject,ActivityEvent.onDestory))
.subscribe();
實現的功能和上面寫法一模一樣,那麼我們定義一個介面LifecycleManager用於生成這些LifecycleTransformer:
public interface LifecycleManager {
Observable<ActivityEvent> getLifecycle();
<T> LifecycleTransformer<T> bindUntilEvent(ActivityEvent activityEvent);
<T> LifecycleTransformer<T> bindToLifecycle();
<T> LifecycleTransformer<T> bindOnDestroy();
}
接口裡一共提供了4個方法:
getLifecycle():用於獲取提供生命週期的Observable,也就是上文提到的 lifecycleSubject(就是BehaviorSubject)
bindUntilEvent(ActivityEvent activityEvent):根據傳入的生命週期,生成指定的LifecycleTransformer,就是將原Observable繫結到指定Activity生命週期.
bindToLifecycle() : 這個是根據原Observable訂閱與那個生命週期,轉化到它應該在那個生命週期登出,比如在onCreate訂閱就在OnDestroy登出,在onStart訂閱就在onStop登出,在onResume訂閱就在onPause登出,這個適用於在介面可見的時候開始幹什麼事,介面不可見的時候停止幹什麼事情,比如輪播圖.
bindOnDestroy():直接繫結到當Activity介面銷燬的時候Observable登出,這個是bindUntilEvent(ActivityEvent activityEvent)的一種情況,因為用的比較多,我就多寫了這個.
下面介紹一下這個 bindToLifecycle()如何實現,直接上程式碼:
public class LifecycleTransformer<T> implements Observable.Transformer<T, T> {
private Observable<ActivityEvent> lifecycleObservable;
LifecycleTransformer(Observable<ActivityEvent> lifecycleObservable) {
this.lifecycleObservable = lifecycleObservable.share();
}
@Override
public Observable<T> call(Observable<T> sourceObservable) {
return sourceObservable.takeUntil(getLifecycleObservable());
}
@NonNull
private Observable<?> getLifecycleObservable() {
return Observable.combineLatest(lifecycleObservable.first().map(ACTIVITY_LIFECYCLE),
lifecycleObservable.skip(1), new Func2<ActivityEvent, ActivityEvent, Boolean>() {
@Override
public Boolean call(ActivityEvent activityEvent, ActivityEvent event) {
return activityEvent == event;
}
})
.takeFirst(new Func1<Boolean, Boolean>() {
@Override
public Boolean call(Boolean aBoolean) {
return aBoolean;
}
});
}
// 用於生命週期轉化
private static final Func1<ActivityEvent, ActivityEvent> ACTIVITY_LIFECYCLE =
new Func1<ActivityEvent, ActivityEvent>() {
@Override
public ActivityEvent call(ActivityEvent lastEvent) {
switch (lastEvent) {
case onCreate:
return ActivityEvent.onDestory;
case onStart:
return ActivityEvent.onStop;
case onResume:
return ActivityEvent.onPause;
case onPause:
return ActivityEvent.onStop;
case onStop:
return ActivityEvent.onDestory;
case onDestory:
throw new IllegalStateException("Cannot injectRxLifecycle to Activity lifecycle when outside of it.");
default:
throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
}
}
};
}
首先構造方法裡,這次我們只需要拿到lifecycleSubject(lifecycleObservable)即可,不用在傳入ActivityEvent,通過share操作符,是這個lifecycleObservable可以有多個Subscriber.由於這個lifecycleObservable 其實就是BehaviorSubject,上文已經介紹,當有訂閱者時,他會把他被訂閱之前最後一個事件發給這個訂閱者,我們通過first操作符,就可以拿到原Observable訂閱的時候是在那個生命週期訂閱的,然後通過map操作符將訂閱發生的生週期轉化出應該登出的生命週期,這樣登出的生命週期我們就有了,這樣就和構造方法傳入兩個引數的邏輯基本一樣了.
再通過combineLatest操作符將轉化生命週期的Observable(lifecycleObservable.first().map(ACTIVITY_LIFECYCLE))和發射生命週期的Observable(lifecycleObservable.skip(1))聯合起來,再通過takeFirst過濾出指定生命週期的後傳送資料,從而登出原Observable.
將以上種構造方法合併到一個LifecycleTransformer裡後代碼如下:
public class LifecycleTransformer<T> implements Observable.Transformer<T, T> {
private Observable<ActivityEvent> lifecycleObservable;
private ActivityEvent activityEvent;
LifecycleTransformer(Observable<ActivityEvent> lifecycleObservable) {
this.lifecycleObservable = lifecycleObservable.share();
}
LifecycleTransformer(Observable<ActivityEvent> lifecycleObservable, ActivityEvent activityEvent) {
this.lifecycleObservable = lifecycleObservable;
this.activityEvent = activityEvent;
}
@Override
public Observable<T> call(Observable<T> sourceObservable) {
return sourceObservable.takeUntil(getLifecycleObservable());
}
@NonNull
private Observable<?> getLifecycleObservable() {
if (activityEvent != null) {
lifecycleObservable.takeFirst(new Func1<ActivityEvent, Boolean>() {
@Override
public Boolean call(ActivityEvent event) {
return activityEvent == event;
}
});
}
return Observable.combineLatest(lifecycleObservable.first().map(ACTIVITY_LIFECYCLE),
lifecycleObservable.skip(1), new Func2<ActivityEvent, ActivityEvent, Boolean>() {
@Override
public Boolean call(ActivityEvent activityEvent, ActivityEvent event) {
return activityEvent == event;
}
})
.takeFirst(new Func1<Boolean, Boolean>() {
@Override
public Boolean call(Boolean aBoolean) {
return aBoolean;
}
});
}
// 用於生命週期轉化
private static final Func1<ActivityEvent, ActivityEvent> ACTIVITY_LIFECYCLE =
new Func1<ActivityEvent, ActivityEvent>() {
@Override
public ActivityEvent call(ActivityEvent lastEvent) {
switch (lastEvent) {
case onCreate:
return ActivityEvent.onDestory;
case onStart:
return ActivityEvent.onStop;
case onResume:
return ActivityEvent.onPause;
case onPause:
return ActivityEvent.onStop;
case onStop:
return ActivityEvent.onDestory;
case onDestory:
throw new IllegalStateException("Cannot injectRxLifecycle to Activity lifecycle when outside of it.");
default:
throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
}
}
};
}
也是由於這個 生命週期轉化的問題,導致在onPause及其以後的生命週期裡訂閱一個Observable的時候,需要事先注入RxLifecycle,下文會講到.
那麼我們接下來要做的事情就是獲取和Activity一一對應的LifecycleManager了.
這一塊我借鑑的是Glide的做法:Glide.with(activity):
我們知道當Fragment通過FragmentManager加入到Activity中後,具有和activity基本相同的生命週期(忽略其他),那麼我們通過這個Fragment傳送activity的使命週期事件,同樣能達到預期的效果,再讓這個Fragment實現 LifecycleManager 介面不就行了,上一波程式碼:
public class LifecycleFragment extends Fragment implements LifecycleManager {
private final BehaviorSubject<ActivityEvent> lifecycleSubject;
public LifecycleFragment() {
lifecycleSubject = BehaviorSubject.create();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
lifecycleSubject.onNext(ActivityEvent.onCreate);
super.onCreate(savedInstanceState);
}
@Override
public void onStart() {
lifecycleSubject.onNext(ActivityEvent.onStart);
super.onStart();
}
@Override
public void onResume() {
lifecycleSubject.onNext(ActivityEvent.onResume);
super.onResume();
}
@Override
public void onPause() {
lifecycleSubject.onNext(ActivityEvent.onPause);
super.onPause();
}
@Override
public void onStop() {
lifecycleSubject.onNext(ActivityEvent.onStop);
super.onStop();
}
@Override
public void onDestroy() {
lifecycleSubject.onNext(ActivityEvent.onDestory);
super.onDestroy();
}
@Override
public Observable<ActivityEvent> getLifecycle() {
return lifecycleSubject.asObservable();
}
@Override
public <T> LifecycleTransformer<T> bindUntilEvent(final ActivityEvent activityEvent) {
return new LifecycleTransformer<>(lifecycleSubject, activityEvent);
}
@Override
public <T> LifecycleTransformer<T> bindToLifecycle() {
return new LifecycleTransformer<>(lifecycleSubject);
}
@Override
public <T> LifecycleTransformer<T> bindOnDestroy() {
return bindUntilEvent(ActivityEvent.onDestory);
}
}
這樣我們就可以通過這個LifecycleFragment 既能獲取到Activity的生命週期,又能獲取到 各種 LifecycleTransformer.
這個時候我們就需要獲取這個和Activity一一對應的LifecycleFragment 即 LifecycleManager:
public class RxLifecycle {
private static final String FRAGMENT_TAG = "lifecycle_tag"; public static LifecycleManager with(Activity 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;
}
通過FragmentManager 將一個空的LifecycleFragment 附加TAG新增到Activity中,如果再次呼叫同過TAG拿到.這樣我們就拿到了LifecycleManager,就可以獲取各種LifecycleTransformer了.
這時候我們就要想那個在onPause以後以後訂閱的Observable使用bindToLifecycle 為什麼要先注入RxLifecycle的問題:
若果你在onPause之前,這個Activity都沒有使用過RxLifecycle,這個是個這個介面並沒有加入這個空的LifecycleFragment,導致在onPause的時候首次呼叫會出現LifecycleFragment回撥的生命週期是onCreate->onStart->onPause->onStop(沒有onResume,是因為這個Fragment在建立的時候介面已經不可見了,所以不會回撥這個),所以在使用bindToLifecycle()的時候,生命週期的轉化會出問題.自行補腦吧,不詳細分析了.
所以我不得不加入一個預先注入的方法,在Activity的onCreate方法呼叫:
/**
* @param context ensure context can be cast {@link Activity}
*/
public static void injectRxLifecycle(Context context) {
with(context);
}
其實最後呼叫的還是 with(activity)的方法,就是先把這個LifecycleFragment和Activity繫結.保證在呼叫bindToLifecycle()的時候,生命週期轉化正常.如果你有更好的處理方法,請及時告知我,萬分感謝!
上文說到,這個RxLifecycle庫,也可以在自定義view中使用,其實也簡單,就是通過view.getContext(),獲取上下文,那view是放在Activity上,那個這個上下文必然是Activity,然而實事還是打臉了,V7包下的AppCompatXXXView,獲取的上下文是一個TintContextWrapper,不能強轉成Activity,我的內心是崩潰的,哪位大佬知道怎麼班,快告訴我,膝蓋送上!
RxLifecycle類全部程式碼:
public class RxLifecycle {
private static final String FRAGMENT_TAG = "lifecycle_tag";
/**
* @param context ensure context can be cast {@link Activity}
*/
public static void injectRxLifecycle(Context context) {
with(context);
}
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;
}
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;
}
public static LifecycleManager with(Fragment fragment) {
return with(fragment.getActivity());
}
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);
}
throw new ClassCastException(context.getClass().getSimpleName() + " can\'t cast Activity !");
}
public static LifecycleManager with(View view) {
return with(view.getContext());
}
private static void injectRxLifecycle(Object object) {
if (object instanceof View) {
with((View) object);
} else {
with(object);
}
}
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 !");
}
}
About me
email: [email protected]
github: https://github.com/dhhAndroid
專案地址: https://github.com/dhhAndroid/RxLifecycle
您的一個star是對我最大的鼓勵!
---------------------
作者:huiAndroid
來源:CSDN
原文:https://blog.csdn.net/huiAndroid/article/details/78116228
版權宣告:本文為博主原創文章,轉載請附上博文連結!