RxAndroid和Retrofit结合使用-网络调用和生命周期分析

说明

这是我在项目使用RxAndroid、RxJava和Retrofit时的一些记录和分析。

记录1:

网络操作相关

在使用RxAndroid和Retrofit进行网络操作时,有如下这些代码

代码:

 getMyFollowingBoard(mTokenType, mTokenAccess, mIndex, mLimit)
                .doOnUnsubscribe(new Action0() {
                    @Override
                    public void call() {
                        Logger.d("Unsubscribe");
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(只有响应操作的打印...

打印结果:

(正确联网返回)

[ModuleFragment:onStart:230]:
[ModuleFragment:onNext:251]:
[ModuleFragment:onCompleted:236]:
[ModuleFragment:call:221]: Unsubscribe

分析:

  • 网络的调用在Fragment中,没有做相关Fragment生命周期绑定处理。
  • 打印结果的前四行,没有问题,是正确的调用。

疑问:

但是我没有在任何地方调用取消订阅的操作,为什么会能够响应doOnUnsubscribe方法?

有必要贴一下doOnUnsubscribe的说明图

doOnUnsubscribe的说明图

方法说明:Observables被取消订阅时候调用。

总结:

在RxJavaCallAdapterFactory类里面层层调用最后能看到这样的代码

// Attempt to cancel the call if it is still in-flight on unsubscription.
      subscriber.add(Subscriptions.create(new Action0() {
        @Override public void call() {
          call.cancel();//这是Retrofit网络取消方法
        }
      }));

这段代码是给 subscribe 增加一个 unsubscribe 的事件。 也就是请求完成的时候,会自动对 call 进行一个终止,也就是 http 的 close 行为。

资料来自于:
https://segmentfault.com/a/1190000004077117?utm_source=tuicool&utm_medium=referral

记录2:

有关网络调用和生命周期

代码:

修改上面的代码,添加线程休眠2秒,网络操作在onActivityCreated生命周期中调用

getMyFollowingBoard(mTokenType, mTokenAccess, mIndex, mLimit)
 .filter(new Func1<FollowingBoardListBean, Boolean>() {
                    @Override
                    public Boolean call(FollowingBoardListBean followingBoardListBean) {
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return true;
                    }
                })
                .doOnUnsubscribe(new Action0() {
                    @Override
                    public void call() {
                        Logger.d("Unsubscribe");
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(只有响应操作的打印...)

打印结果:

(进入Fragment,再马上退出)

[BaseFragment:onCreateView:95]: MyAttentionBoardFragment
[BaseFragment:onActivityCreated:106]: MyAttentionBoardFragment
—>按下返回键,退出这个Fragment
[BaseFragment:onPause:124]: MyAttentionBoardFragment
[BaseFragment:onDestroyView:136]: MyAttentionBoardFragment
[BaseFragment:onDestroy:143]: MyAttentionBoardFragment
[MyAttentionBoardFragment:onNext:90]:
[MyAttentionBoardFragment:onCompleted:79]:
[MyAttentionBoardFragment:call:70]: Unsubscribe

分析:

  • 我在联网的方法中添加了让线程休眠2秒的方法,模拟网络状态不好的情况下,联网结果返回很慢。
  • 可以看到,我在onActivityCreated中开始联网,由于延迟在马上退出后,在我整个Fragment都已经销毁,联网结果才返回。

问题:

在负责显示网络内容的Fragment都销毁的情况还接收联网结果调用是没有意义的。没有用的对象占用内存。

解决办法:

在RxJava中存在这个类
rx.subscriptions.CompositeSubscription

类说明:Subscription that represents a group of Subscriptions that are unsubscribed together.
All methods of this class are thread-safe.
翻译:有关于Subscriptions的集合类,用于取消订阅操作。

所以我们可以使用它保存我们的Subscription联网操作,在合适的地方取消
集成在BaseFragment用于统一管理。

代码:

public abstract class BaseFragment extends Fragment {
         private CompositeSubscription mCompositeSubscription;

    public CompositeSubscription getCompositeSubscription() {
        if (this.mCompositeSubscription == null) {
            this.mCompositeSubscription = new CompositeSubscription();
        }

        return this.mCompositeSubscription;
    }

    public void addSubscription(Subscription s) {
        if (this.mCompositeSubscription == null) {
            this.mCompositeSubscription = new CompositeSubscription();
        }

        this.mCompositeSubscription.add(s);
    }

     @Override
    public void onDestroy() {
        super.onDestroy();
          //在销毁时统一取消
        if (this.mCompositeSubscription != null) {
            this.mCompositeSubscription.unsubscribe();
        }

    }

}

添加上面代码到BaseFragment后,再次实验

打印结果:

[BaseFragment:onCreateView:95]: MyAttentionBoardFragment
[BaseFragment:onActivityCreated:106]: MyAttentionBoardFragment
[BaseFragment:onResume:118]: MyAttentionBoardFragment
[BaseFragment:onPause:124]: MyAttentionBoardFragment
[BaseFragment:onDestroy:143]: MyAttentionBoardFragment
[MyAttentionBoardFragment:call:72]: Unsubscribe //看到取消了
[BaseFragment:onDetach:155]: MyAttentionBoardFragment

总结:

这样就实现了RxAndroid和Retrofit在Fragment的优化(Activity同理)

这在Goog官方MVP架构中,同样采用这样的方式处理生命周期同步。

记录3

AndroidObservable

在这篇博客http://blog.danlew.net/2014/10/08/grokking-rxjava-part-4/
也就是深入浅出RxJava(四:响应式安卓开发)的原文中又提到
这样的代码实现

AndroidObservable.bindActivity(this, retrofitService.getImage(url))
    .subscribeOn(Schedulers.io())
    .subscribe(bitmap -> myImageView.setImageBitmap(bitmap);

实现:当你的Activity或Fragment完成,同样也会发出停止网络操作信号

这里有AndroidObservable源码

但是相信大家在compile 'io.reactivex:rxandroid:1.1.0'

  • 编译之后是找不到AndroidObservable这个类。 http://stackoverflow.com/ 上也有很多问的人,为什么找不到? 同学仔细看原文的发布时间 2014年10月,2年前的博文啊!

原因

AppObservable and its bind methods have been completely eradicated. There were a number of problems with it:
说明:AppObservable(也就是进化版的AndroidObservable),存在很多问题,已经从RxAndroid中移除

问题如下:
1. It tried to auto-unsubscribe, but it would only do so if the sequence emitted an item after the Activity or Fragment paused. As a consequence, sequences that never end might never unsubscribe.
2. It was designed to defend against notifications after pause, but it appears that bug only occurred due to a subtle logic issue in the HandlerScheduler.
3. It automatically called observeOn(AndroidSchedulers.mainThread()), whether you wanted it or not.

最后:

  1. 官方推荐的RxLifecycle来管理生命周期,个人觉得RxLifecycle太死板,它需我们继承extends RxAppCompatActivity,会影响我们的代码层级。
  2. Check whether you need to add observeOn(AndroidSchedulers.mainThread()) to the sequence.,好好写代码吧。
  3. 目前使用CompositeSubscription来管理订阅者的订阅是比较常见的做法。当然是在有需要的情况下使用。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: RxJava和Retrofit是一种经常结合使用的技术,主要是因为它们都能够协同工作,优化Android应用的性能。 具体而言,RxJava是一种响应式编程框架,可以通过异步数据流的方式处理数据。Retrofit则是一个RESTful框架,用于与服务器交互。因此,RxJava可以被用于处理从Retrofit返回的数据流。 这两个框架的结合使用可以让Android应用更快地处理数据并更好地应对网络请求。同时,通过使用RxJava的转换操作符,我们可以将从Retrofit返回的数据进行快速处理和转换。 ### 回答2: RXJava是一个响应式编程库,而Retrofit则是针对REST API进行网络请求和响应解析的框架。这两者结合使用,可以实现优雅的网络请求,并让代码更加简洁易懂。 Retrofit默认使用的是同步方法,这意味着如果在主线程中执行网络请求,就会阻塞主线程,造成卡顿甚至应用崩溃。为了避免这种情况,我们可以使用RXJava中的异步调度器,将网络请求放在IO线程中执行,并在请求完成后将结果回调到主线程中处理,保证应用的流畅性和响应性。 RXJava还提供了丰富的操作符,如map、filter、flatMap等,能够对网络请求的响应数据进行快速处理和转换,将数据转换成我们需要的格式,例如对象或列表。这样在显示数据时,可以节省大量的代码和时间。 另外,由于网络请求可能出现异常、网络超时等情况,我们需要对这些异常情况进行处理。RXJava提供了专门的异常处理操作符,如onErrorReturn、onErrorResumeNext等,能够快速捕获和处理网络请求异常,并在发生异常时执行相应的操作。 综上所述,RXJava和Retrofit结合使用,能够方便地实现优雅的网络请求和数据处理,以及有效地解决网络请求可能出现的异常情况,为开发者提供了更加便捷、高效、安全的开发体验。 ### 回答3: RxJava和Retrofit是目前Android开发中非常流行的两个库。他们都不是新兴的库,RxJava是由Netflix公司开发的响应式编程库,是在Java Future的基础上进行开发的。Retrofit是由Square公司开发的网络请求库。在进行Android开发时,我们一般会经常使用Retrofit来完成网络请求的操作,而配合使用RxJava可以让我们更加方便的处理网络请求的结果。 为什么要使用RxJava和RetrofitRetrofit是一个基于OkHttp的RESTful API请求框架,可以让我们通过定义相应的接口,来进行网络请求使用简单而且很快,这也是为什么它会被Android开发者广泛使用的原因。而RxJava则是将异步事件组合在一起的响应式编程库,可以让我们以响应式的方式来处理网络请求的结果。因此,当我们结合使用这两个库时,就可以更加高效地完成Android的开发。 如何使用RxJava和Retrofit使用RxJava和Retrofit大致的流程如下: 1. 在build.gradle文件中添加RetrofitRxJava的依赖: ``` implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'io.reactivex.rxjava2:rxjava:2.2.19' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' ``` 2. 定义Retrofit接口: ``` public interface ApiService { @GET("users") Observable<List<User>> getUsers(); } ``` 3. 使用RetrofitRxJava进行网络请求: ``` ApiService apiService = RetrofitClient.getInstance().create(ApiService.class); apiService.getUsers() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<User>>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(List<User> users) { // 成功获取到用户列表 } @Override public void onError(Throwable e) { // 网络请求失败 } @Override public void onComplete() { } }); ``` 在这个示例中,我们首先定义了一个ApiService接口,其中包含了我们需要进行网络请求的方法。在进行网络请求时,我们可以使用Retrofit的create()方法来实例化一个ApiService对象,然后使用subscribeOn()和observeOn()方法进行线程调度,最后使用subscribe()方法订阅Observer对象,即可完成网络请求的操作。 结论 RxJava和Retrofit可以很好地配合使用,使我们可以简洁、高效地处理网络请求的结果。配合使用可以大大提高我们的开发效率,同时也可以减少我们的代码量,让我们可以更加专注于业务逻辑的实现。因此,在进行Android开发时,建议使用这两个库来完成网络请求的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值