美文网首页Rx系列RxJava + RetrofitRxjava学习
Android RxJava 实际应用讲解:(有条件)网络请求轮

Android RxJava 实际应用讲解:(有条件)网络请求轮

作者: Carson带你学安卓 | 来源:发表于2017-11-14 09:45 被阅读4036次

    前言

    • Rxjava,由于其基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎。
    Github截图

    如果还不了解RxJava,请看文章:Android:这是一篇 清晰 & 易懂的Rxjava 入门教程

    • RxJava如此受欢迎的原因,在于其提供了丰富 & 功能强大的操作符,几乎能完成所有的功能需求
    • 今天,我将为大家带来 Rxjava创建操作符的实际开发需求场景:有条件的轮询需求 ,并结合RetrofitRxJava 实现,希望大家会喜欢。
    1. 本系列文章主要基于 Rxjava 2.0
    2. 接下来的时间,我将持续推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、应用场景、背压等等 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记!!
    示意图

    目录

    示意图

    1. 需求场景

    示意图

    注:关于 Rxjava中的repeatWhen() 操作符的使用请看文章Android RxJava:功能性操作符 全面讲解


    2. 功能说明

    采用Get方法对 金山词霸API 按规定时间重复发送网络请求,从而模拟 轮询 需求实现

    1. 停止轮询的条件 = 当轮询到第4次时
    2. 采用 Gson 进行数据解析
    金山词典

    3. 具体实现

    下面,我将结合 RetrofitRxJava 实现 有条件的轮询需求

    3.1 步骤说明

    1. 添加依赖
    2. 创建 接收服务器返回数据 的类
    3. 创建 用于描述网络请求 的接口(区别于Retrofit传统形式)
    4. 创建 Retrofit 实例
    5. 创建 网络请求接口实例 并 配置网络请求参数(区别于Retrofit传统形式)
    6. 发送网络请求(区别于Retrofit传统形式)
    7. 发送网络请求
    8. 对返回的数据进行处理

    本实例侧重于说明 RxJava 的轮询需求,关于Retrofit的使用请看文章:这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)

    3.2 步骤实现

    步骤1: 添加依赖

    a. 在 Gradle加入Retrofit库的依赖

    build.gradle

    dependencies {
    
    // Android 支持 Rxjava
    // 此处一定要注意使用RxJava2的版本
    compile 'io.reactivex.rxjava2:rxjava:2.0.1'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    
    // Android 支持 Retrofit
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    
    // 衔接 Retrofit & RxJava
    // 此处一定要注意使用RxJava2的版本
    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
    
    // 支持Gson解析
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    
    }
    

    b. 添加 网络权限
    AndroidManifest.xml

    <uses-permission android:name="android.permission.INTERNET"/>
    
    步骤2:创建 接收服务器返回数据 的类
    • 金山词霸API 的数据格式说明如下:
    // URL模板
    http://fy.iciba.com/ajax.php
    
    // URL实例
    http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world
    
    // 参数说明:
    // a:固定值 fy
    // f:原文内容类型,日语取 ja,中文取 zh,英语取 en,韩语取 ko,德语取 de,西班牙语取 es,法语取 fr,自动则取 auto
    // t:译文内容类型,日语取 ja,中文取 zh,英语取 en,韩语取 ko,德语取 de,西班牙语取 es,法语取 fr,自动则取 auto
    // w:查询内容
    
    • 示例
    API格式说明
    • 根据 金山词霸API 的数据格式,创建 接收服务器返回数据 的类:

    Translation.java

    public class Translation {
    
        private int status;
    
        private content content;
        private static class content {
            private String from;
            private String to;
            private String vendor;
            private String out;
            private int errNo;
        }
    
        //定义 输出返回数据 的方法
        public void show() {
            Log.d("RxJava", content.out );
        }
    }
    
    步骤3:创建 用于描述网络请求 的接口

    采用 注解 + Observable<...>接口描述 网络请求参数

    GetRequest_Interface.java

    public interface GetRequest_Interface {
    
        @GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20world")
        Observable<Translation> getCall();
         // 注解里传入 网络请求 的部分URL地址
        // Retrofit把网络请求的URL分成了两部分:一部分放在Retrofit对象里,另一部分放在网络请求接口里
        // 如果接口里的url是一个完整的网址,那么放在Retrofit对象里的URL可以忽略
        // 采用Observable<...>接口 
        // getCall()是接受网络请求数据的方法
    }
    
    接下来的步骤均在RxJavafixRxjava.java内实现(请看注释)

    RxJavafixRxjava.java

    public class RxJavafixRetrofit extends AppCompatActivity {
    
        private static final String TAG = "Rxjava";
    
        // 设置变量 = 模拟轮询服务器次数
        private int i = 0 ;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
                            // 步骤1:创建Retrofit对象
                            Retrofit retrofit = new Retrofit.Builder()
                                    .baseUrl("http://fy.iciba.com/") // 设置 网络请求 Url
                                    .addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
                                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
                                    .build();
    
                            // 步骤2:创建 网络请求接口 的实例
                            GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
    
                            // 步骤3:采用Observable<...>形式 对 网络请求 进行封装
                            Observable<Translation> observable = request.getCall();
    
                            // 步骤4:发送网络请求 & 通过repeatWhen()进行轮询
                            observable.repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
                                @Override
                                // 在Function函数中,必须对输入的 Observable<Object>进行处理,此处使用flatMap操作符接收上游的数据
                                public ObservableSource<?> apply(@NonNull Observable<Object> objectObservable) throws Exception {
                                    // 将原始 Observable 停止发送事件的标识(Complete() /  Error())转换成1个 Object 类型数据传递给1个新被观察者(Observable)
                                    // 以此决定是否重新订阅 & 发送原来的 Observable,即轮询
                                    // 此处有2种情况:
                                    // 1. 若返回1个Complete() /  Error()事件,则不重新订阅 & 发送原来的 Observable,即轮询结束
                                    // 2. 若返回其余事件,则重新订阅 & 发送原来的 Observable,即继续轮询
                                    return objectObservable.flatMap(new Function<Object, ObservableSource<?>>() {
                                        @Override
                                        public ObservableSource<?> apply(@NonNull Object throwable) throws Exception {
    
                                            // 加入判断条件:当轮询次数 = 5次后,就停止轮询
                                            if (i > 3) {
                                                // 此处选择发送onError事件以结束轮询,因为可触发下游观察者的onError()方法回调
                                                return Observable.error(new Throwable("轮询结束"));
                                            }
                                            // 若轮询次数<4次,则发送1Next事件以继续轮询
                                            // 注:此处加入了delay操作符,作用 = 延迟一段时间发送(此处设置 = 2s),以实现轮询间间隔设置
                                            return Observable.just(1).delay(2000, TimeUnit.MILLISECONDS);
                                        }
                                    });
    
                                }
                            }).subscribeOn(Schedulers.io())               // 切换到IO线程进行网络请求
                                    .observeOn(AndroidSchedulers.mainThread())  // 切换回到主线程 处理请求结果
                                    .subscribe(new Observer<Translation>() {
                                        @Override
                                        public void onSubscribe(Disposable d) {
                                        }
    
                                        @Override
                                        public void onNext(Translation result) {
                                            // e.接收服务器返回的数据
                                            result.show() ;
                                            i++;
                                        }
    
                                        @Override
                                        public void onError(Throwable e) {
                                            // 获取轮询结束信息
                                            Log.d(TAG,  e.toString());
                                        }
    
                                        @Override
                                        public void onComplete() {
    
                                        }
                                    });
    
                        }
        }
    

    3.3 测试结果

    示意图

    4. Demo地址

    Carson_Ho的Github地址 = RxJava2实战系列:有条件的轮询

    关于无条件的网络请求轮询,具体请看文章Android RxJava 实际应用讲解:网络请求轮询


    5. 总结

    • 本文主要讲解了 Rxjava创建操作符的实际开发需求场景:有条件轮询需求 ,并结合RetrofitRxJava 实现
    • 下面我将结合 实际场景应用 & Rxjava的相关使用框架(如RetrofitEventbus ,继续对 AndroidRxjava 的实际开发需求场景进行深入讲解 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记

    请点赞!因为你的鼓励是我写作的最大动力!

    相关文章阅读


    欢迎关注Carson_Ho的简书!

    不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度

    相关文章

      网友评论

      • 旋哥:使用 Observable.intervalRange(1, 3, 2,1,TimeUnit.SECONDS)不更方便吗?
      • 在追风筝丶:楼主,我这边有个这样的需求,首先我这边有个list<String>的集合作为消息源,发出后,根据list中的每个str来做轮询,轮询的时间间隔要根据后台的返回做出调整,并且每个str对应的间隔都会不一样,难道要像上文那样为每个str给一个全局的i来记录时间间隔吗?想问下用rx有更优雅的实现方式不。
      • 老西子:代码排版太乱了,费眼睛.
      • 张先森_VIP:怎么跟activity的生命周期绑定使用呢?
      • 夜幕流星雨:代码排版有点乱,很实用

      本文标题:Android RxJava 实际应用讲解:(有条件)网络请求轮

      本文链接:https://www.haomeiwen.com/subject/cmocsxtx.html