天天看點

Android開發之深度項目設計探索(二)

《Android開發之深度項目設計探索(一)》 這篇文章中,主要描述了深度項目架構設計會涉及到的一些知識點,那麼這篇文章主要介紹的是 RxLifecycle 使用及源碼分析。

RxLifecycle :

在Android進行面試的時候,經常會被問到的就是Android的記憶體洩漏、洩漏場景、洩漏原因以及解決辦法。如果你提到了Rxjava2,面試官可能會接連發問Rxjava2在使用過程中會有一些什麼問題?這時就可以談到Rxjava如果在一些特定場景沒有及時解綁訂閱可能會導緻記憶體洩漏。

洩漏的原因是:當RxJava釋出一個訂閱後,此時頁面執行了finish的生命周期,但訂閱邏輯還未完成。如果沒有及時取消訂閱,就會導緻Activity/Fragment無法被回收,進而引發記憶體洩漏。但是相應的,Rxjava系列也提供了解決辦法,那就是使用RxLifecycle 。

RxLifecycle官方文檔

通過官方文檔了解發現,RxLifecycle庫的使用和內建也是簡單和快捷的

A:RxLifecycle對應的依賴(最新版本)

// 這是RxLifecycle最主要的依賴
implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.2'

// If you want to bind to Android-specific lifecycles
//如果你想綁定Android的生命周期
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.2'

// If you want pre-written Activities and Fragments you can subclass as providers
//如果想在預先寫好的Activities and Fragments,你可以作為其父類的子類
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2'

// If you want pre-written support preference Fragments you can subclass as providers
//如果想在預先支援的 Fragments,你可以作為其父類的子類
implementation 'com.trello.rxlifecycle2:rxlifecycle-components-preference:2.2.2'

// If you want to use Navi for providers
// Android使用的庫,繼承NaviActivity使用
implementation 'com.trello.rxlifecycle2:rxlifecycle-navi:2.2.2'

// If you want to use Android Lifecycle for providers
//如果你想為其提供Android生命周期
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle:2.2.2'

// If you want to use Kotlin syntax
//如果你想使用Kotlin文法
implementation 'com.trello.rxlifecycle2:rxlifecycle-kotlin:2.2.2'

// If you want to use Kotlin syntax with Android Lifecycle
//如果你想使用Kotlin文法作用在Android生命周期上
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle-kotlin:2.2.2'

           

下面是一些基本的使用和說明:

首先是 綁定生命周期:

myObservable.compose(RxLifecycle.bind(lifecycle)).subscribe();
           

接着是 綁定特殊的生命周期(onStart onStop等等):

myObservable.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
    .subscribe();
           

然後是 通過RxLifecycle在适當的時間來結束:

myObservable.compose(RxLifecycleAndroid.bindActivity(lifecycle)).subscribe();
           

通過文檔我們可以知道:如果在onStart( )這個生命周期裡面綁定,它就會在onStop()這個終止綁定;如果我們在onPause( )之後訂閱, 那麼它就會在其下一個生命周期終止綁定,(在onPause( )之後訂閱,因為onStop()是其下一個生命周期,如果Activity執行到了這裡,就會解綁)

下面上一段代碼加深RxLifecycle的了解和使用:

public class LifeActivity extends RxAppCompatActivity{

    @Override
    protected void onStart() {
        super.onStart();

        Observable.interval(2, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(this.bindToLifecycle())
                .subscribe();
    }

}

           

理論上我們需要使用compose操作符,然後加上bindToLifecycle即可完成簡單的使用(注意:這裡的 LifeActivity繼承的是RxAppCompatActivity)看到了這裡,可能疑惑的是,RxLifecycle具體的綁定該如何了解?裡面的生命周期又是如何操作的?

是這樣,這裡的生命周期是由 LifecycleProvider<T> 來提供的,實作的方式有以下四種:

1:繼承父類,RxActivity, RxFragment

2:使用

Navi

以及 Rxlifecycle-navi

3:使用

Android's lifecycle

4:自己編寫實作

首先看第一種:也就是上面的代碼,直接繼承RxAppCompatActivity,然後點開RxAppCompatActivity源碼會發現很多事情,這個後面說。

第二種:繼承NaviActivity(需要導入上面提供的Navi對應的依賴)下面是參考代碼

public class NaviLifeActivity extends NaviActivity{

    private final LifecycleProvider<ActivityEvent> provider
            = NaviLifecycle.createActivityLifecycleProvider(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initLifecycle();
    }
      
    private void initLifecycle(){
        Observable.interval(2, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(provider.bindToLifecycle())
                .subscribe();
    }
}
           

第三種和第四種由于涉及到另外的内容這裡就不描述了。

值得一提的是:compose方法需在subscribeOn方法之後使用。

RxLifecycle源碼分析:

說到源碼,我們首先進入RxAppCompatActivity看看,因為compose(this.bindToLifecycle()) 這句API裡面的this,代表的就是目前繼承了RxAppCompatActivity的子類,奔着研究分析的精神,下面是

RxAppCompatActivity 的源碼:

public abstract class RxAppCompatActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {

    private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();

    @Override
    @NonNull
    @CheckResult
    public final Observable<ActivityEvent> lifecycle() {
        return lifecycleSubject.hide();
    }

    @Override
    @NonNull
    @CheckResult
    public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
        return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
    }

    @Override
    @NonNull
    @CheckResult
    public final <T> LifecycleTransformer<T> bindToLifecycle() {
        return RxLifecycleAndroid.bindActivity(lifecycleSubject);
    }

    @Override
    @CallSuper
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        lifecycleSubject.onNext(ActivityEvent.CREATE);
    }

    @Override
    @CallSuper
    protected void onStart() {
        super.onStart();
        lifecycleSubject.onNext(ActivityEvent.START);
    }

    @Override
    @CallSuper
    protected void onResume() {
        super.onResume();
        lifecycleSubject.onNext(ActivityEvent.RESUME);
    }

    @Override
    @CallSuper
    protected void onPause() {
        lifecycleSubject.onNext(ActivityEvent.PAUSE);
        super.onPause();
    }

    @Override
    @CallSuper
    protected void onStop() {
        lifecycleSubject.onNext(ActivityEvent.STOP);
        super.onStop();
    }

    @Override
    @CallSuper
    protected void onDestroy() {
        lifecycleSubject.onNext(ActivityEvent.DESTROY);
        super.onDestroy();
    }
}

           

可以看到在Activity具體生命周期裡面進行了對應的事件發送!

1:BehaviorSubject與ActivityEvent

RxAppCompatActivity源碼中内部第一行代碼是建立了一個BehaviorSubject執行個體對象,裡面的泛型是ActivityEvent,首先看下 ActivityEvent ,

/**
 * Lifecycle events that can be emitted by Activities.
 */
public enum ActivityEvent {

    CREATE,
    START,
    RESUME,
    PAUSE,
    STOP,
    DESTROY

}
           

哦,細心的你一眼就看到了這是個枚舉,裡面的value對應的就是Activity生命周期的那些生命周期(因為在生命周期裡面進行了發射嘛);那麼,什麼是BehaviorSubject?BehaviorSubject的由于源碼較多這裡就不貼出來了,這個類它繼承了Subject<T>,那 Subject<T> 又是什麼?源碼如下:

public abstract class Subject<T> extends Observable<T> implements Observer<T> {
    /**
     * Returns true if the subject has any Observers.
     * <p>The method is thread-safe.
     * @return true if the subject has any Observers
     */
    public abstract boolean hasObservers();

    /**
     * Returns true if the subject has reached a terminal state through an error event.
     * <p>The method is thread-safe.
     * @return true if the subject has reached a terminal state through an error event
     * @see #getThrowable()
     * @see #hasComplete()
     */
    public abstract boolean hasThrowable();

    /**
     * Returns true if the subject has reached a terminal state through a complete event.
     * <p>The method is thread-safe.
     * @return true if the subject has reached a terminal state through a complete event
     * @see #hasThrowable()
     */
    public abstract boolean hasComplete();

    /**
     * Returns the error that caused the Subject to terminate or null if the Subject
     * hasn't terminated yet.
     * <p>The method is thread-safe.
     * @return the error that caused the Subject to terminate or null if the Subject
     * hasn't terminated yet
     */
    @Nullable
    public abstract Throwable getThrowable();

    /**
     * Wraps this Subject and serializes the calls to the onSubscribe, onNext, onError and
     * onComplete methods, making them thread-safe.
     * <p>The method is thread-safe.
     * @return the wrapped and serialized subject
     */
    @NonNull
    public final Subject<T> toSerialized() {
        if (this instanceof SerializedSubject) {
            return this;
        }
        return new SerializedSubject<T>(this);
    }
}
           

哦,上帝,Subject繼承了Observable、又實作了Observer接口,這也就說明Subject即可作為被觀察者,也可以作為觀察者。同理,他的子類BehaviorSubject也具備同樣的功能。

下面是關于BehaviorSubject操作符的一張圖:

Android開發之深度項目設計探索(二)

BehaviorSubject

BehaviorSubject的簡單了解就是,發送離訂閱最近的上一個值,沒有上一個值的時候會發送預設值,接下來(如果有資料)則繼續發射原始Observable的資料。

2:bindUntilEvent( ActivityEvent event) 、LifecycleTransformer、takeUntil

在RxAppCompatActivity 源碼中我們看到了bindUntilEvent()這個方法,最終的的傳回值類型是 LifecycleTransformer 那這個LifecycleTransformer又是什麼?

public final class LifecycleTransformer<T> implements ObservableTransformer<T, T>,
                                                      FlowableTransformer<T, T>,
                                                      SingleTransformer<T, T>,
                                                      MaybeTransformer<T, T>,
                                                      CompletableTransformer
{
    final Observable<?> observable;

    LifecycleTransformer(Observable<?> observable) {
        checkNotNull(observable, "observable == null");
        this.observable = observable;
    }

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

經過源碼可以發現,這個LifecycleTransformer實作了大量的XXXTransformer,内部的方法大都使用了apply方法,這個方法實則是調用了takeUntil操作符,那麼這個takeUntil操作符是什麼意思?

Android開發之深度項目設計探索(二)

takeUntil

takeUntil操作符簡單了解就是,當第二個Observable發射了一項資料或者終止時,丢棄原Observable發射的任何資料。注意:這裡是滿足條件丢棄任何發送的資料(該操作符的應用場景是不是,在onDestroy( )裡面取消訂閱,解決記憶體洩漏的隐患)

3:bindToLifecycle()

我們知道,綁定的API是bindToLifecycle()這一行代碼,那麼我們就抽絲剝繭,根據RxAppCompatActivity源碼得知,bindToLifecycle()這行代碼最終傳回了 RxLifecycleAndroid.bindActivity(lifecycleSubject),源碼跟進,進入到了RxLifecycleAndroid,下面是 RxLifecycleAndroid 源碼:

public class RxLifecycleAndroid {

    private RxLifecycleAndroid() {
        throw new AssertionError("No instances");
    }

    /**
     * Binds the given source to an Activity lifecycle.
     * <p>
     * This helper automatically determines (based on the lifecycle sequence itself) when the source
     * should stop emitting items. In the case that the lifecycle sequence is in the
     * creation phase (CREATE, START, etc) it will choose the equivalent destructive phase (DESTROY,
     * STOP, etc). If used in the destructive phase, the notifications will cease at the next event;
     * for example, if used in PAUSE, it will unsubscribe in STOP.
     * <p>
     * Due to the differences between the Activity and Fragment lifecycles, this method should only
     * be used for an Activity lifecycle.
     *
     * @param lifecycle the lifecycle sequence of an Activity
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source during the Activity lifecycle
     */
    @NonNull
    @CheckResult
    public static <T> LifecycleTransformer<T> bindActivity(@NonNull final Observable<ActivityEvent> lifecycle) {
        return bind(lifecycle, ACTIVITY_LIFECYCLE);
    }

    /**
     * Binds the given source to a Fragment lifecycle.
     * <p>
     * This helper automatically determines (based on the lifecycle sequence itself) when the source
     * should stop emitting items. In the case that the lifecycle sequence is in the
     * creation phase (CREATE, START, etc) it will choose the equivalent destructive phase (DESTROY,
     * STOP, etc). If used in the destructive phase, the notifications will cease at the next event;
     * for example, if used in PAUSE, it will unsubscribe in STOP.
     * <p>
     * Due to the differences between the Activity and Fragment lifecycles, this method should only
     * be used for a Fragment lifecycle.
     *
     * @param lifecycle the lifecycle sequence of a Fragment
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source during the Fragment lifecycle
     */
    @NonNull
    @CheckResult
    public static <T> LifecycleTransformer<T> bindFragment(@NonNull final Observable<FragmentEvent> lifecycle) {
        return bind(lifecycle, FRAGMENT_LIFECYCLE);
    }

    /**
     * Binds the given source to a View lifecycle.
     * <p>
     * Specifically, when the View detaches from the window, the sequence will be completed.
     * <p>
     * Warning: you should make sure to use the returned Transformer on the main thread,
     * since we're binding to a View (which only allows binding on the main thread).
     *
     * @param view the view to bind the source sequence to
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source during the View lifecycle
     */
    @NonNull
    @CheckResult
    public static <T> LifecycleTransformer<T> bindView(@NonNull final View view) {
        checkNotNull(view, "view == null");

        return bind(Observable.create(new ViewDetachesOnSubscribe(view)));
    }

    // Figures out which corresponding next lifecycle event in which to unsubscribe, for Activities
    private static final Function<ActivityEvent, ActivityEvent> ACTIVITY_LIFECYCLE =
        new Function<ActivityEvent, ActivityEvent>() {
            @Override
            public ActivityEvent apply(ActivityEvent lastEvent) throws Exception {
                switch (lastEvent) {
                    case CREATE:
                        return ActivityEvent.DESTROY;
                    case START:
                        return ActivityEvent.STOP;
                    case RESUME:
                        return ActivityEvent.PAUSE;
                    case PAUSE:
                        return ActivityEvent.STOP;
                    case STOP:
                        return ActivityEvent.DESTROY;
                    case DESTROY:
                        throw new OutsideLifecycleException("Cannot bind to Activity lifecycle when outside of it.");
                    default:
                        throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
                }
            }
        };

    // Figures out which corresponding next lifecycle event in which to unsubscribe, for Fragments
    private static final Function<FragmentEvent, FragmentEvent> FRAGMENT_LIFECYCLE =
        new Function<FragmentEvent, FragmentEvent>() {
            @Override
            public FragmentEvent apply(FragmentEvent lastEvent) throws Exception {
                switch (lastEvent) {
                    case ATTACH:
                        return FragmentEvent.DETACH;
                    case CREATE:
                        return FragmentEvent.DESTROY;
                    case CREATE_VIEW:
                        return FragmentEvent.DESTROY_VIEW;
                    case START:
                        return FragmentEvent.STOP;
                    case RESUME:
                        return FragmentEvent.PAUSE;
                    case PAUSE:
                        return FragmentEvent.STOP;
                    case STOP:
                        return FragmentEvent.DESTROY_VIEW;
                    case DESTROY_VIEW:
                        return FragmentEvent.DESTROY;
                    case DESTROY:
                        return FragmentEvent.DETACH;
                    case DETACH:
                        throw new OutsideLifecycleException("Cannot bind to Fragment lifecycle when outside of it.");
                    default:
                        throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
                }
            }
        };

}
           

嗯,首先看到bindActivity(final Observable<ActivityEvent> lifecycle)這個方法,這個方法最終傳回了bind(lifecycle, ACTIVITY_LIFECYCLE);

請注意,前方高能: ACTIVITY_LIFECYCLE,這個ACTIVITY_LIFECYCLE的源碼也是上面的截圖,可以看到通過switch語句進行條件篩選最終傳回ActivityEvent這個枚舉裡面的屬性值(仔細觀看的話源碼下面還有Fragment對應的生命周期),可能你會問,為什麼這是對應的生命周期?讓我們首先看回bind(lifecycle, ACTIVITY_LIFECYCLE); 這個方法,點進去看,進入到了 RxLifecycle 這個類,源碼如下:

public class RxLifecycle {

    private RxLifecycle() {
        throw new AssertionError("No instances");
    }

    /**
     * Binds the given source to a lifecycle.
     * <p>
     * When the lifecycle event occurs, the source will cease to emit any notifications.
     *
     * @param lifecycle the lifecycle sequence
     * @param event the event which should conclude notifications from the source
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source at the specified event
     */
    @Nonnull
    @CheckReturnValue
    public static <T, R> LifecycleTransformer<T> bindUntilEvent(@Nonnull final Observable<R> lifecycle,
                                                                @Nonnull final R event) {
        checkNotNull(lifecycle, "lifecycle == null");
        checkNotNull(event, "event == null");
        return bind(takeUntilEvent(lifecycle, event));
    }

    private static <R> Observable<R> takeUntilEvent(final Observable<R> lifecycle, final R event) {
        return lifecycle.filter(new Predicate<R>() {
            @Override
            public boolean test(R lifecycleEvent) throws Exception {
                return lifecycleEvent.equals(event);
            }
        });
    }

    /**
     * Binds the given source to a lifecycle.
     * <p>
     * This helper automatically determines (based on the lifecycle sequence itself) when the source
     * should stop emitting items. Note that for this method, it assumes <em>any</em> event
     * emitted by the given lifecycle indicates that the lifecycle is over.
     *
     * @param lifecycle the lifecycle sequence
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source whenever the lifecycle emits
     */
    @Nonnull
    @CheckReturnValue
    public static <T, R> LifecycleTransformer<T> bind(@Nonnull final Observable<R> lifecycle) {
        return new LifecycleTransformer<>(lifecycle);
    }

    /**
     * Binds the given source to a lifecycle.
     * <p>
     * This method determines (based on the lifecycle sequence itself) when the source
     * should stop emitting items. It uses the provided correspondingEvents function to determine
     * when to unsubscribe.
     * <p>
     * Note that this is an advanced usage of the library and should generally be used only if you
     * really know what you're doing with a given lifecycle.
     *
     * @param lifecycle the lifecycle sequence
     * @param correspondingEvents a function which tells the source when to unsubscribe
     * @return a reusable {@link LifecycleTransformer} that unsubscribes the source during the Fragment lifecycle
     */
    @Nonnull
    @CheckReturnValue
    public static <T, R> LifecycleTransformer<T> bind(@Nonnull Observable<R> lifecycle,
                                                      @Nonnull final Function<R, R> correspondingEvents) {
        checkNotNull(lifecycle, "lifecycle == null");
        checkNotNull(correspondingEvents, "correspondingEvents == null");
        return bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents));
    }

    private static <R> Observable<Boolean> takeUntilCorrespondingEvent(final Observable<R> lifecycle,
                                                                       final Function<R, R> correspondingEvents) {
        return Observable.combineLatest(
            lifecycle.take(1).map(correspondingEvents),
            lifecycle.skip(1),
            new BiFunction<R, R, Boolean>() {
                @Override
                public Boolean apply(R bindUntilEvent, R lifecycleEvent) throws Exception {
                    return lifecycleEvent.equals(bindUntilEvent);
                }
            })
            .onErrorReturn(Functions.RESUME_FUNCTION)
            .filter(Functions.SHOULD_COMPLETE);
    }
}

           

最終執行到了 RxLifecycle 這個類源碼裡面的最後的兩個方法!

4:takeUntilCorrespondingEvent()

takeUntilCorrespondingEvent這個方法内容較多,首先分析第一個,combineLatest操作符,這個操作符是指 将傳進來的BehaviorSubject的事件進行了一次分割;假設我們現在在onCreate()方法裡面進行RxLifecycle的綁定,那麼這裡的lifecycle.take(1).map(correspondingEvents)簡單了解其對應的代碼就是 RxLifecycleAndroid源碼 裡面的ACTIVITY_LIFECYCLE 中的,

case CREATE:
 return ActivityEvent.DESTROY;
           

另外,lifecycle.skip(1)意味着除去第一個(ActivityEvent.CREATE),保留剩下的ActivityEvent枚舉值

new BiFunction<R, R, Boolean>這行代碼是對屬性值進行判斷:對比結果是

false,false,fasle,false,true

最後,onErrorReturn和filter這兩行代碼分别是對異常的處理以及判斷是否應該結束訂閱、

final class Functions {

    static final Function<Throwable, Boolean> RESUME_FUNCTION = new Function<Throwable, Boolean>() {
        @Override
        public Boolean apply(Throwable throwable) throws Exception {
            if (throwable instanceof OutsideLifecycleException) {
                return true;
            }

            //noinspection ThrowableResultOfMethodCallIgnored
            Exceptions.propagate(throwable);
            return false;
        }
    };

    static final Predicate<Boolean> SHOULD_COMPLETE = new Predicate<Boolean>() {
        @Override
        public boolean test(Boolean shouldComplete) throws Exception {
            return shouldComplete;
        }
    };

    static final Function<Object, Completable> CANCEL_COMPLETABLE = new Function<Object, Completable>() {
        @Override
        public Completable apply(Object ignore) throws Exception {
            return Completable.error(new CancellationException());
        }
    };

    private Functions() {
        throw new AssertionError("No instances!");
    }
}

           

綜上:本次訂閱,當Activity走到onStart生命周期時,為false,訂閱不會取消,直到onDestroy,為true,訂閱取消

5:最後調用的方法

根據邏輯,上面最終調用了下面的代碼:

public static <T, R> LifecycleTransformer<T> bind(@Nonnull final Observable<R> lifecycle) {
        return new LifecycleTransformer<>(lifecycle);
    }

           

可以看到,這裡最終生成了一個LifecycleTransformer。

源碼邏輯總結:

A:繼承了RxAppCompatActivity的子類Activity,在每個生命的周期裡,BehaviorSubject發射相對應的事件

B:bind方法主要是做指派、比對、判斷

C:LifecycleTransformer内部進行takeUntil操作符,如果是true,就終止訂閱,反之

如果這篇文章對你有幫助,希望各位看官留下寶貴的star,謝謝。

Ps:著作權歸作者所有,轉載請注明作者, 商業轉載請聯系作者獲得授權,非商業轉載請注明出處(開頭或結尾請添加轉載出處,添加原文url位址),文章請勿濫用,也希望大家尊重筆者的勞動成果。

繼續閱讀