Android RxLifecycle使用详解

github官网

RxLifecycle依赖

  • 注意:本文使用的版本是3.1版本
implementation 'com.trello.rxlifecycle3:rxlifecycle:3.1.0'

// If you want to bind to Android-specific lifecycles
implementation 'com.trello.rxlifecycle3:rxlifecycle-android:3.1.0'

// If you want pre-written Activities and Fragments you can subclass as providers
implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0'

// If you want pre-written support preference Fragments you can subclass as providers
implementation 'com.trello.rxlifecycle3:rxlifecycle-components-preference:3.1.0'

// If you want to use Android Lifecycle for providers
implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle:3.1.0'

// If you want to use Kotlin syntax
implementation 'com.trello.rxlifecycle3:rxlifecycle-kotlin:3.1.0'

// If you want to use Kotlin syntax with Android Lifecycle
implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle-kotlin:3.1.0'

// If you want to use Navi for providers
// DEPRECATED: Use rxlifecycle-android-lifecycle instead. This will be removed in a future release.
implementation 'com.trello.rxlifecycle3:rxlifecycle-navi:3.1.0'

RxLifecycle介绍

RxLifecycle目的:解决RxJava使用中的内存泄漏问题。

RxLifecycle核心思想:通过监听Activity、Fragment的生命周期,来自动断开订阅防止内存泄漏。

例如,当使用RxJava订阅并执行耗时任务后,当Activity被finish时,如果耗时任务还未完成,没有及时取消订阅,就会导致Activity无法被回收,从而引发内存泄漏。

为了解决这个问题,就产生了RxLifecycle,让RxJava变得有生命周期感知,使得其能及时取消订阅,避免出现内存泄漏问题。

它可以让Observable发布的事件和当前的组件绑定,实现生命周期同步。
从而实现当前组件生命周期结束时,自动取消对Observable订阅。

目前网上对RxJava的内存泄漏有几种方案

  1. 手动为RxJava的每一次订阅进行控制,指定在哪个生命周期方法调用时取消订阅;
  2. 当前组件生命周期结束时,自动取消对Observable订阅

上述两种方式我都使用过,RxLifecycle显然对于第一种方式,更简单直接,并且能够在Activity/Fragment容器的指定生命周期取消订阅,实在是好用。

RxJava的内存泄漏案例

每隔1秒打印,无限循环:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("xyh", "onCreate: ");
        Observable.interval(2, 1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()) // interval 默认在新线程,所以需要切换回主线程
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        Log.e("xyh", +aLong + "");
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("xyh", "onDestroy: ");
    }
}

打印结果

2020-03-11 22:10:09.004 15261-15261/com.xyh.rxlifecycle E/xyh: onCreate: 
2020-03-11 22:10:11.029 15261-15261/com.xyh.rxlifecycle E/xyh: 0
2020-03-11 22:10:12.029 15261-15261/com.xyh.rxlifecycle E/xyh: 1
2020-03-11 22:10:13.029 15261-15261/com.xyh.rxlifecycle E/xyh: 2
2020-03-11 22:10:14.028 15261-15261/com.xyh.rxlifecycle E/xyh: 3
2020-03-11 22:10:15.050 15261-15261/com.xyh.rxlifecycle E/xyh: onDestroy: 
2020-03-11 22:10:15.061 15261-15261/com.xyh.rxlifecycle E/xyh: 4
2020-03-11 22:10:16.029 15261-15261/com.xyh.rxlifecycle E/xyh: 5
2020-03-11 22:10:17.028 15261-15261/com.xyh.rxlifecycle E/xyh: 6

我们发现执行onDestroy()方法后,还会继续执行,因为没有及时解除订阅,在退出activity的时候,异步线程还在执行,对activity还存在引用,此时就会产生内存泄漏。

RxLifecycle的使用

添加依赖

 //处理rxjava内存泄漏   
implementation 'com.trello.rxlifecycle3:rxlifecycle:3.1.0'
implementation 'com.trello.rxlifecycle3:rxlifecycle-android:3.1.0'
implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0'

Activity/Fragment需继承RxAppCompatActivity/RxFragment,目前支持的有如下:
在这里插入图片描述

1. 继承RxAppCompatActivity :

Activity需要继承RxAppCompatActivity,Fragment需要继承RxFragment。

public class MainActivity extends RxAppCompatActivity {
      ...
      ...
}

在项目中针对base类的容器中继承实现对应的Rx类即可

public abstract class BaseActivity extends RxAppCompatActivity {

}

2. 使用compose操作符绑定容器生命周期

有两种方式:

方式1:使用bindToLifecycle()

以Activity为例,在Activity中使用bindToLifecycle()方法,完成Observable发布的事件和当前的组件绑定,实现生命周期同步。从而实现当前组件生命周期结束时,自动取消对Observable订阅,代码如下:

在onResume()进行绑定订阅,则在onPause()进行解除订阅,生命周期是两两对应的。

public class MainActivity extends RxAppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.e("xyh", "onCreate: ");

        //在某个生命周期进行绑定,在对应的生命周期进行订阅解除,当执行onDestory()时, 自动解除订阅
        Observable.interval(3, 2, TimeUnit.SECONDS)
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.e("xyh", "解除了订阅");
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .compose(this.<Long>bindToLifecycle())
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        //在onCreate()中启动,一直运行到onDestory()
                        Log.e("xyh", +aLong + "");
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("xyh", "onDestroy: ");
    }
}

方式2:使用bindUntilEvent()

使用ActivityEvent类,其中的CREATE、START、 RESUME、PAUSE、STOP、 DESTROY分别对应生命周期内的方法。使用bindUntilEvent指定在哪个生命周期方法调用时取消订阅:

public class MainActivity extends RxAppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.e("xyh", "onCreate: ");

        Observable.interval(3, 2, TimeUnit.SECONDS)
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.e("xyh", "解除了订阅");
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
         
                .compose(this.<Long>bindUntilEvent(ActivityEvent.DESTROY)) // 手动指定在生命周期onDestory()时,取消订阅。
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        //在onCreate()中启动,一直运行到onDestory()
                        Log.e("xyh", +aLong + "");
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("xyh", "onDestroy: ");
    }
}

打印结果:

我们发现执行,在退出activity的时候,解除了订阅,不再继续执行,解决类内存泄漏。

04-03 17:10:38.296 29186-29186/? E/xyh: onCreate: 
04-03 17:10:41.311 29186-29219/com.xiaoyehai.rxlifecycle E/xyh: 0
04-03 17:10:43.310 29186-29219/com.xiaoyehai.rxlifecycle E/xyh: 1
04-03 17:10:45.311 29186-29219/com.xiaoyehai.rxlifecycle E/xyh: 2
04-03 17:10:46.723 29186-29186/com.xiaoyehai.rxlifecycle E/xyh: 解除了订阅
04-03 17:10:46.724 29186-29186/com.xiaoyehai.rxlifecycle E/xyh: onDestroy: 

以Activity为例,主要有如下两种方法:

bindToLifecycle()  //在某个生命周期进行绑定,在对应的生命周期进行订阅解除。
//在onResume()进行绑定订阅,则在onPause()进行解除订阅,生命周期是两两对应的。

bindUntilEvent(@NonNull ActivityEvent event)  //该方法指定在哪个生命周期方法调用时取消订阅。

Fragment也有同样的两种方法,只是方法名会有所不同。

其中ActivityEvent是一个枚举类,对应于Activity的生命周期:

public enum ActivityEvent {

    CREATE,
    START,
    RESUME,
    PAUSE,
    STOP,
    DESTROY

}

不需要继承RxAppCompatActivity/RxFragment实现

上面的方式需要继承RxAppCompatActivity,如果我们自己有BaseActivity,所以不能继承RxActvivty,RxAppCompatActivity、RxFragment,NaviActivity。

为了保持代码的灵活性,我们只需要添加下面的依赖即可:

// 使用Android生命周期作为提供者
 implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle:3.1.0'

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("xyh", "onCreate: ");

        LifecycleProvider<Lifecycle.Event> provider = AndroidLifecycle.createLifecycleProvider(this);
        Observable.interval(3, 2, TimeUnit.SECONDS)
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.e("xyh", "解除了订阅");
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .compose(provider.<Long>bindToLifecycle())
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        //在onCreate()中启动,一直运行到onDestory()
                        Log.e("xyh", +aLong + "");
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("xyh", "onDestroy: ");
    }
}

2020-03-11 22:19:29.329 16751-16751/com.xyh.rxlifecycle E/xyh: 0
2020-03-11 22:19:31.327 16751-16751/com.xyh.rxlifecycle E/xyh: 1
2020-03-11 22:19:33.108 16751-16751/com.xyh.rxlifecycle E/xyh: 解除了订阅
2020-03-11 22:19:33.111 16751-16751/com.xyh.rxlifecycle E/xyh: onDestroy: 

把LifecycleProvider抽取到BaseActivity中

public abstract class BaseActivity extends AppCompatActivity {

    protected LifecycleProvider<Lifecycle.Event> mLifecycleProvider;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());

        mLifecycleProvider = AndroidLifecycle.createLifecycleProvider(this);

        init();
    }

    protected abstract int getLayoutId();

    protected abstract void init();
}
public class MainActivity extends BaseActivity {

    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void init() {
        Log.e("xyh", "init: ");
        Observable.interval(2, 1, TimeUnit.SECONDS)
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.e("xyh", "解除了订阅");
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .compose(mLifecycleProvider.<Long>bindToLifecycle())
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        //在onCreate()中启动,一直运行到onDestory()
                        Log.e("xyh", +aLong + "");
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("xyh", "onDestroy: ");
    }
}

这里我们要用到LifecycleProvide这个接口。值得一提的是这个接口已经在RxAppCompatActivity中实现了,所以为什么可以继承RxAppCompatActivity,赋予接口引用就可以使用它了。

MVP中使用RxLifecycle

这只是一个很简单的mvp案例,主要是演示RxLifecycle在mvp中的使用,在项目实际开发中可以进行封装。

不需要继承RxAppCompatActivity/RxFragment方式

public class MainActivity extends BaseActivity implements MainView {

    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void init() {
        Log.e("xyh", "init: ");
        MainPresenter mainPresenter = new MainPresenter(mLifecycleProvider, this);
        mainPresenter.loadData();
    }

    @Override
    public void onSuccess(String s) {
        Log.e("xyh", "onSuccess: " + s);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("xyh", "onDestroy: ");
    }
}

public class MainModel {

    public Observable<Long> loadData() {

        Observable<Long> observable =
                Observable
                        .interval(2, 1, TimeUnit.SECONDS)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());

        return observable;
    }
}
public class MainPresenter {

    public LifecycleProvider<Lifecycle.Event> lifecycleProvider;
    public MainView mainView;
    private final MainModel mMainModel;

    public MainPresenter(LifecycleProvider<Lifecycle.Event> lifecycleProvider, MainView mainView) {
        this.lifecycleProvider = lifecycleProvider;
        this.mainView = mainView;
        mMainModel = new MainModel();
    }

    public void loadData() {
        mMainModel.loadData()
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.e("xyh", "解除了订阅");
                    }
                })
                .compose(lifecycleProvider.<Long>bindToLifecycle())
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Long aLong) {
                        mainView.onSuccess(aLong + "");
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });


    }
}

使用继承RxAppCompatActivity/RxFragment方式

MainPresenter mainPresenter = new MainPresenter(bindToLifecycle(), this);
mainPresenter.loadData();
public class MainPresenter {

    public LifecycleTransformer lifecycleTransformer;
    public MainView mainView;
    private final MainModel mMainModel;

    public MainPresenter(LifecycleTransformer lifecycleTransformer, MainView mainView) {
        this.lifecycleTransformer = lifecycleTransformer;
        this.mainView = mainView;
        mMainModel = new MainModel();
    }

    public void loadData() {
        mMainModel.loadData()
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.e("xyh", "解除了订阅");
                    }
                })
                .compose(lifecycleTransformer)
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Long aLong) {
                        mainView.onSuccess(aLong + "");
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}

Fragment中使用RxLifecycle

Fragment中使用和在Activity中的使用基本一致。

public abstract class BaseFragment extends Fragment {

    protected LifecycleProvider<Lifecycle.Event> mLifecycleProvider;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view=inflater.inflate(getLayoutId(),container,false);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mLifecycleProvider = AndroidLifecycle.createLifecycleProvider(this);
		 //要用this,he fragment的生命周期绑定在一起如果使用getActivity()的话就是和Activity的生命周期绑定在一起
        //mLifecycleProvider = AndroidLifecycle.createLifecycleProvider(getActivity());


        init();

    }

    protected abstract int getLayoutId();

    protected abstract void init();


}

public class HomeFrgament extends BaseFragment {
    @Override
    protected int getLayoutId() {
        return R.layout.fragment_home;
    }

    @Override
    protected void init() {

        Log.e("xyh", "init: ");
        Observable.interval(2, 1, TimeUnit.SECONDS)
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.e("xyh", "解除了订阅");
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .compose(mLifecycleProvider.<Long>bindToLifecycle())
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        //在onCreate()中启动,一直运行到onDestory()
                        Log.e("xyh", +aLong + "");
                    }
                });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.e("xyh", "HomeFrgament==onDestroyView: " );
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("xyh", "HomeFrgament==onDestroy: " );
    }
}

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CountDownLatch是Java中的一个同步工具类,用于控制多个线程的执行顺序。它通过一个计数器来实现,该计数器初始化为一个正整数,每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器的值减到0时,所有等待的线程就会被唤醒继续执行。 在Android中,CountDownLatch可以用于等待多个异步操作完成后再执行某个任务,或者等待多个线程都达到某个状态后再继续执行。 下面是CountDownLatch的基本使用方法: 1. 创建CountDownLatch对象,并指定计数器的初始值。 ```java CountDownLatch latch = new CountDownLatch(3); // 计数器初始值为3 ``` 2. 在需要等待的地方调用`await()`方法,使当前线程进入等待状态,直到计数器值为0时才会继续执行。 ```java try { latch.await(); // 等待计数器值为0 } catch (InterruptedException e) { e.printStackTrace(); } ``` 3. 在需要通知其他线程继续执行的地方调用`countDown()`方法,将计数器的值减1。 ```java latch.countDown(); // 计数器减1 ``` 下面是一个简单的示例,演示了如何使用CountDownLatch等待多个线程完成后再执行某个任务: ```java import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(3); for (int i = 0; i < 3; i++) { final int threadNum = i; new Thread(() -> { try { Thread.sleep(1000); System.out.println("Thread " + threadNum + " completed."); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } try { latch.await(); System.out.println("All threads completed. Start executing the task..."); // 执行任务 } catch (InterruptedException e) { e.printStackTrace(); } } } ``` 在上面的示例中,我们创建了一个初始值为3的CountDownLatch对象。然后创建了3个线程,每个线程会在执行完任务后将计数器减1。主线程调用`await()`方法等待计数器的值变为0,当所有线程都执行完任务后,主线程才会继续执行并输出"All threads completed. Start executing the task..."。 希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值