retrofit2+MVP+rxjava2+rxlifecycle2 为啥无法解决内存泄露

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了retrofit2+MVP+rxjava2+rxlifecycle2 为啥无法解决内存泄露相关的知识,希望对你有一定的参考价值。

使用retrofit2+MVP+rxjava2+rxlifecycle2,用 .compose(getActivity().<BaseResponse<List<DeviceTypeEntity>>>bindToLifecycle()) 进行解决内存泄露, GC后发现在内存分析时并没有释放内存,这是怎么回事? 求大神帮助下,非常感谢

随着android第三库的普及, RxJava 和 RxAndroid ( tiveX/RxAndroid )越来越被人熟知,简洁的语法,配合Java8 Lambda表达式,使代码的结构更加清晰,通过线程调度器更容易控制和切换线程,种种优点,使用它的人也越来越多。但是使用不好,很容易导致内存泄露。 Rxlifecycle (b.com/trello/RxLifecycle )就使被用来严格控制由于发布了一个订阅后,由于没有及时取消,导致Activity/Fragment无法销毁导致的内存泄露 。
RxJava和RxAndroid
compile 'io.reactivex:rxandroid:1.0.1'compile 'io.reactivex:rxjava:1.0.16'12

Rxlifecycle
compile 'com.trello:rxlifecycle:0.3.0'
compile 'com.trello:rxlifecycle-components:0.3.0'12

Rxlifecycle 使用
Activity/Fragment需继承RxAppCompatActivity/RxFragment,目前支持的有RxAppCompatActivity、RxFragment、RxDialogFragment、RxFragmentActivity。
一、bindToLifecycle()方法
在子类使用Observable中的compose操作符,调用,完成Observable发布的事件和当前的组件绑定,实现生命周期同步。从而实现当前组件生命周期结束时,自动取消对Observable订阅。
Observable.interval(1, TimeUnit.SECONDS)
.compose(this.bindToLifecycle())
.subscribe(new Action1<Long>()
@Override
public void call(Long num)
Log.i(TAG, " " +num);

);12345678

二、bindUntilEvent() 方法
使用ActivityEvent类,其中的CREATE、START、 RESUME、PAUSE、STOP、 DESTROY分别对应生命周期内的方法。使用bindUntilEvent指定在哪个生命周期方法调用时取消订阅。
Observable.interval(1, TimeUnit.SECONDS) .compose(this.bindUntilEvent(ActivityEvent.PAUSE))
.subscribe(mSub);
参考技术A 看你使用了 getActivity,那么你是在fragment中使用的rx,所以你需要做的是绑定fragment的生命周期,而不是绑定 activity的周期,你的fragment继承RxFragment,然后使用this.bindXXX。不要使用context或者activity,这两是不属于fragment生命周期内的

MVP+Retrofit+RxJava+Dagger框架




MVP和Retrofit还有Dagger的使用和我们平常是差不多的,这里就不过多的讲解了
主要来讲解一下RxJava和Retrofit的结合

下面我们来看一下RxJava和retrofit的结合使用,为了使Rxjava与retrofit结合,我们需要在Retrofit对象建立的时候添加一句代码addCallAdapterFactory(RxJavaCallAdapterFactory.create()),当然你还需要在build.gradle文件中添加如下依赖:
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

完整的代码如下:
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.douban.com/v2/")
        .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create()))
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//支持RxJava
        .build();

然后我们还需要修改RetrofitService 中的代码:
public interface RetrofitService 
    @GET("book/search")
    Observable<Book> getSearchBook(@Query("q") String name,
                                    @Query("tag") String tag, @Query("start") int start,
                                    @Query("count") int count);

可以看到,在原来的RetrofitService 中我们把getSearchBook方法返回的类型Call改为了Observable,也就是被观察者。其他都没变。然后就是创建RetrofitService 实体类:
RetrofitService service = retrofit.create(RetrofitService.class);

和上面一样,创建完RetrofitService ,就可以调用里面的方法了:
Observable<Book> observable =  service.getSearchBook("Hello", null, 0, 1);

其实这一步,就是创建了一个rxjava中observable,即被观察者,有了被观察者,就需要一个观察者,且订阅它:
observable.subscribeOn(Schedulers.io())//请求数据的事件发生在io线程
          .observeOn(AndroidSchedulers.mainThread())//请求完成后在主线程更显UI
          .subscribe(new Observer<Book>() //订阅
              @Override
              public void onCompleted() 
                  //所有事件都完成,可以做些操作。。。
              
              @Override
              public void onError(Throwable e) 
                  e.printStackTrace(); //请求过程中发生错误
              
              @Override
              public void onNext(Book book) //这里的book就是我们请求接口返回的实体类    
              
           

在上面中我们可以看到,事件的消费在Android主线程,所以我们还要在build.gradle中添加如下依赖:
compile 'io.reactivex:rxandroid:1.2.0'

这样我们就引入了RxAndroid,RxAndroid其实就是对RxJava的扩展。比如上面这个Android主线程在RxJava中就没有,因此要使用的话就必须得引用RxAndroid。




以上是关于retrofit2+MVP+rxjava2+rxlifecycle2 为啥无法解决内存泄露的主要内容,如果未能解决你的问题,请参考以下文章

android查询天气demo,基于mvp+kotlin+rxjava2+room+retrofit2

RxJava2+Retrofit2+RxLifecycle2使用MVP模式构建项目

一套整合主流HTTP网络图片加载MVP(RxJava2+Dagger2)架构的快速高效的开发框架RxEasyAndroid

一套整合主流HTTP网络图片加载MVP(RxJava2+Dagger2)架构的快速高效的开发框架RxEasyAndroid

如何使用Retrofit2,RxJava2,Gson TypeAdapterFActory正确映射Gson?

浅谈Retrofit2+Rxjava2