动手实现一个轻量级无侵入性的RxJava自动注销库RxLifecycle

*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

一. 概述

RxLifecycle是一个轻量级,侵入性低的RxJava注销管理库.他不会改变原有项目Activity的继承结构,轻松实现RxJava在Android平台下的自动注销,甚至你在自定义view的时候使用RxJava都能轻松完整自动注销功能.如果你的项目在开发中期想要引入RxJava相关的自动注销库,这个库将是你不错的选择,原因就在他的入侵性低.

项目地址: 欢迎star

https://github.com/dhhAndroid/RxLifecycle

gradle 依赖:

compile 'com.dhh:rxlifecycle:1.0'

二. 使用方法

把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();
                registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
                    @Override
                    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                        RxLifecycle.injectRxLifecycle(activity);
                    }
                    //other mothods
                });
            }
        }


注意:

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(暂不支持V7包下的AppCompatXXXView),Fragment,V4.Fragment等.

在自定义view用使用

如果你在自定义view的时候里面使用的RxJava,以及View内部有retrofit+RxJava的网络访问,已经RxJava操作的耗时数据转换,同样支持一行代码管理RxJava自动注销,确保你的view不是继承自AppCompatXXXView,暂不支持.用法和在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操作符演示图:

takeUntil
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.

BehaviorSubject
  // 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操作符类似):

first
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

项目地址: https://github.com/dhhAndroid/RxLifecycle

您的一个star是对我最大的鼓励!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容