美文网首页
Retrofit+rxjava学习记录

Retrofit+rxjava学习记录

作者: 蒲小帅丶 | 来源:发表于2018-09-27 15:56 被阅读0次

    参考文章1:Android 教你一步步搭建MVP+Retrofit+RxJava网络请求框架

    Retrofit的认识

    测试网址
    https://api.douban.com/v2/book/search?q=金瓶梅&tag=&start=0&count=1

    image.png
    GET请求

    提取出基础地址 'BASE_URL=https://api.douban.com/v2/'

    @Query

    url的参数拼接

    @GET("book/search")
    Call<Book> getSearchBook(@Query("q") String name,@Query("tag") String tag1)  //name,tag由调入者传入
    ========等价
    @GET("book/search?q=name&tag=tag1")
    Call<Book> getSearchBook()  //name写死了
    
    @QueryMap

    当传入的参数比较多,可以放在map中

     @GET("book/search")
        Call<BookBean> getSearchBook(@QueryMap Map<String ,String > map);//调用者传入
    
    @Path

    用于替换url中的字段

     @GET("group/{id}/users")
        Call<BookBean> groupList(@Path("id") int group,@Query("sort") String sort);
    
    • 分析
      这种接口在group和users之间有个不确定的id需要传入。就用{}括起来,用Path来替换。id的名字可以随意取,只要和@Path中的名字对应就行。如果users后面还有参数,就可以用Query来拼接上。

    POST请求

    @Body

    可以指定一个对象作为HTTP请求体。

    @POST(''users/new'')
    Call<User> createUser(@Body User user)
    

    它会把我们传入的User实体类转化成用于传输的HTTP请求体。

    @Field

    用于传输表单数据

    @FormUrlEncoded
    @POST(user/edit)
    Call<User> upadeUser(@Field("first_name") String first,@Field("last_name") String last)
    

    注意开头需要加入@FormUrlEncoded注解,不然会报错。

    @Header/@Headers

    用于添加请求头部

    eg:
    @POST("user")
    Call<User> getUser(@Header("Authorization") String authorzation)
    @Headers({
    "Accpet:xxxxxxxxx",
    "User-agent":xxxxxxxxxx"
    })
    @POST("user)
    Call<User> getUser()
    

    对于retrofit的网络请求共有两步:
    1.根据根地址,使用get/post请求去创建接口
    2.创建Retrofit对象

    Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BaseUrl.URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            RetrofitService netApi = retrofit.create(RetrofitService.class);
            Map<String, String> map = new HashMap<>();
            map.put("q", "追风筝的人");
            map.put("tag", "");
            map.put("start", "0");
            map.put("count", "10");
            Call<BookBean> call = netApi.getSearchBook1(map);
            call.enqueue(new Callback<BookBean>() {
                @Override
                public void onResponse(Call<BookBean> call, Response<BookBean> response) {
                    BookBean body = response.body();
                    StringBuilder stringBuilder=new StringBuilder();
                    for (int i = 0; i < body.getBooks().size(); i++) {
                        stringBuilder.append(body.getBooks().get(i).getSubtitle()+"\n");
                    }
                    mTvContent.setText(stringBuilder.toString());
                }
    
                @Override
                public void onFailure(Call<BookBean> call, Throwable t) {
    
                }
            });
    

    ======================分割线======================

    RXJAVA
    image.png
     implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
     implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
    

    根据这可能是最好的RxJava 2.x 入门教程
    约束的术语 被观察者 Observable 称为发射器(上游事件),观察者 Observer 称为接收器(下游事件)

    一些操作符
    Create
    Observable.create(new ObservableOnSubscribe<Integer>() {
                @Override
                public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                    mTvName.append("上游事件发射 1" + "\n");
                    e.onNext(1);
                    mTvName.append("上游事件发射 2" + "\n");
                    e.onNext(2);
                    mTvName.append("上游事件发射 3" + "\n");
                    e.onNext(3);
                    //e.onComlete()
                    mTvName.append("上游事件发射 4" + "\n");
                    e.onNext(4);
    
                }
            }).subscribe(new Observer<Integer>() {
                private int i; //标记
                private Disposable mDisposable;
                @Override
                public void onSubscribe(Disposable d) {
                  mTvName.append("订阅关系是否断开"+d.isDisposed()+"\n");
                  mDisposable=d;
                }
    
                @Override
                public void onNext(Integer integer) {
                    mTvName.append("下游时间接收 value"+integer+"\n");
                    i++;
                    if (i==2)
                    {
                        // 在RxJava 2.x 中,新增的Disposable可以做到切断的操作,
                        // 让Observer观察者不再接收上游事件
                        mDisposable.dispose();//
                        mTvName.append("订阅关系是否断开"+mDisposable.isDisposed()+"\n");
                    }
    
                }
    
                @Override
                public void onError(Throwable e) {
                  mTvName.append("OnError"+e.getMessage());
                }
    
                @Override
                public void onComplete() {
                    mTvName.append("完成"+"\n");
    
                }
            });
    
    image.png
    注意
    • 在发射3之后,直接调用 e.onComlete(),相当于断开了订阅连接。无法接收事件,但是上游还是能发。感觉跟dispose作用一样。
    • 2.x新增 Disposable概念。相当于切断订阅连接。true表示,已经切断,下有事件已经停止接收事件了。
    Map

    作用对发射的每个事件应用一个函数。每一个事件都按照指定的函数去变化


    image.png
    Observable.create(new ObservableOnSubscribe<Integer>() {
                @Override
                public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                   emitter.onNext(1);
                   emitter.onNext(2);
                   emitter.onNext(4);
                }
            }).map(new Function<Integer, String >() {
                @Override
                public String apply(Integer integer) throws Exception {
                    int a=integer*2;
                    return "生产出"+a;
                }
            }).subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    mTvName.append("接收"+s+"\n");
                }
            });
    

    显示结果就是
    接收生产出2
    接收生产出4
    接收生产出8

    注意

    • 此处用了个Consumer是简易版的Observer,他有多重重载,可以自定义你需要处理的信息,我这里调用的是只接受onNext消息的方法,他只提供一个回调接口accept,由于没有onError和onCompete,无法再 接受到onError或者onCompete之后,实现函数回调。 无法回调,并不代表不接收,他还是会接收到onCompete和onError之后做出默认操作,也就是监听者(Consumer)不在接收.

    Zip 两两配对

    作用是合并事件,该合并不是连接,而是两两配对。比如5男8女相亲,不是5男后面接着8女,排成一排这种,而是第一个男生牵手第一个女生,第二个男生牵手第二个女生,类推。第6个到第8个女生就找不到男票了。=。=

    private  Observable<String > getManObservable()
        {
            return  Observable.create(new ObservableOnSubscribe<String>() {
                @Override
                public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                   if (!emitter.isDisposed())
                   {
                       emitter.onNext("帅气男A");
                       mTvName.append("A男出场\n");
                       emitter.onNext("幽默男B");
                       mTvName.append("B男出场\n");
                       emitter.onNext("多金男C");
                       mTvName.append("C男出场\n");
                       emitter.onNext("猥琐男D");
                       mTvName.append("D男出场\n");
                   }
                }
            });
        }
    private  Observable<String > getWomanObservable()
        {
            return  Observable.create(new ObservableOnSubscribe<String>() {
                @Override
                public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                    if (!emitter.isDisposed())
                    {
                        mTvName.append("A女出场\n");
                        emitter.onNext("漂亮女A");
                        mTvName.append("B女出场\n");
                        emitter.onNext("活波女B");
                        mTvName.append("C女出场\n");
                        emitter.onNext("拜金女C");
    
    
                    }
                }
            });
        }
    
    Observable.zip(getManObservable(), getWomanObservable(), new BiFunction<String, String, String>() {
                @Override
                public String apply(String s, String s2) throws Exception {
                    return s+"-配对了-"+s2+"\n";
                }
            }).subscribe(new Observer<String>() {
                @Override
                public void onSubscribe(Disposable d) {
    
    
                }
    
                @Override
                public void onNext(String s) {
                    mTvName.append("配对结果:"+s);
    
                }
    
                @Override
                public void onError(Throwable e) {
    
                }
    
                @Override
                public void onComplete() {
    
                }
            });
    
    image.png

    男生先都全部出场,然后女生在挨个上场,跟序号对应领走。有点像非诚勿扰。O(∩_∩)O哈哈~。不过又不同,女生没有随机选择的权利。

    Concat

    作用就是把发射器按照顺序连接起来。


    image.png
      Observable.concat(Observable.just(1,2,3), Observable.just(4,5,6))
                    .subscribe(new Consumer<Integer>() {
                        @Override
                        public void accept(@NonNull Integer integer) throws Exception {
                            mTvName.append("concat : "+ integer + "\n");
                        
                        }
                    });
    
    • 这里的just的作用就是依次把数据发出去,供onNext接收

    FlatMap

    作用,把一个发射器Observable通过某种方法转换成多个Observables,然后在把这些Observables装进一个单一的发射器Observable中。flatmap不能保证事件的顺序,如需保证,需要用到Concatmap
    实际用法:多个网络请求依次依赖。比如用户注册成功后需要自动登录,我们只需要先通过注册接口注册用户信息,注册成功后马上调用登录接口进行自动登录即可

     Observable.create(new ObservableOnSubscribe<Integer >() {
                @Override
                public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                    emitter.onNext(1);
                    emitter.onNext(2);
                    emitter.onNext(3);
                    emitter.onNext(4);
                }
            }).flatMap(new Function<Integer, ObservableSource<String >>() {
                @Override
                public ObservableSource<String > apply(Integer integer) throws Exception {
                    List<String > list=new ArrayList<>();
                    for (int i = 0; i < 10; i++) {
                        list.add("I am is"+integer);
                    }
                    int delaytime= (int) (1+Math.random()*10);
                    return Observable.fromIterable(list).delay(delaytime, TimeUnit.MILLISECONDS);
                }
            }).subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<String>() {
                        @Override
                        public void onSubscribe(Disposable d) {
                        }
                        @Override
                        public void onNext(String s) {
                             mTvName.append("接收"+s+"\n");
                        }
                        @Override
                        public void onError(Throwable e) {
    
                        }
                        @Override
                        public void onComplete() {
    
                        }
                    });
    
    image.png

    concatMap

    cancatMap于faltMap的区别就是保证了顺序。

    把上述代码的flatMap修改成  concatMap
    
    
    image.png

    顺序就一样了。

    distinct 去重操作
    Observable.just(1,2,3,43,2,3,4312)
                    .distinct().subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                  mTvName.append("value"+integer+"\n");
                }
            });
    

    输出只有:1,2,3,4,5

    Filter 过滤器
    image.png
    Observable.just(1,23,4,-2,45,11,-23)
                    .filter(new Predicate<Integer>() {
                        @Override
                        public boolean test(Integer integer) throws Exception {
                            return integer<5;
                        }
                    })
                    .subscribe(new Consumer<Integer>() {
                        @Override
                        public void accept(Integer integer) throws Exception {
                             mTvName.append("小于5的数"+integer+"\n");
                        }
                    });
    

    输出:1,4,-2,-23

    buffer

    buffer接收两个参数(count,skip). count 意思每几个一组,skip步长,跳过几个。
    下面的例子 buffer(2,3)意思就是把数据分为2个一组,第一组分完之后,跳过3个,在取两个数据一组。直到不能分。
    eg:1,2,3,4,5,6
    1,2---->跳过3个数--->4,5-->跳过3个数---无

    Observable.just(1,2,3,4,5,6)
                    .buffer(2,3)
                    .subscribe(new Consumer<List<Integer>>() {
                        @Override
                        public void accept(List<Integer> integers) throws Exception {
                             mTvName.append("buffer_size"+integers.size()+"\n");
                            for (int i = 0; i < integers.size(); i++) {
                                mTvName.append(integers.get(i)+",");
                            }
                        }
                    });
    

    Timer 延时

    rxjava 2.x用 interval.他们默认都是在新线程,所有需要切换到主线程

    Observable.timer(2,TimeUnit.SECONDS)
    

    interval 延时 3个参数

    Observable.interval(3,2,TimeUint.SECONDS)
    第一次发送时间延长,间隔时间,时间单位
    

    要记得activity销毁的时候,记得删除

    @Override
       protected void doSomething() {
           mDisposable = Observable.interval(3, 2, TimeUnit.SECONDS)
                   .subscribeOn(Schedulers.io())
                   .observeOn(AndroidSchedulers.mainThread()) // 由于interval默认在新线程,所以我们应该切回主线程
                   .subscribe(new Consumer<Long>() {
                       @Override
                       public void accept(@NonNull Long aLong) throws Exception {
                          
                       }
                   });
       }
    
       @Override
       protected void onDestroy() {
           super.onDestroy();
           if (mDisposable != null && !mDisposable.isDisposed()) {
               mDisposable.dispose();
           }
       }
    

    doOnNext

    作用让接收者在接收到数据前单点自己的事情。

    Observable.just(1,2,3,4)
                    .doOnNext(new Consumer<Integer>() {
                        @Override
                        public void accept(Integer integer) throws Exception {
                           mTvName.append("先保存下来"+integer+"\n");
                        }
                    }).subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    mTvName.append("接收到值"+integer+"\n");
                }
            });
    
    
    image.png

    skip

    skip(count)跳过 count的数目开始接收

    take

    take(count) 最多接收 count个数据

    just

    简单发射器,依次调用 onNext

    Single

    只会接收一个参数,而SingleObserver只会调用onError()或者 onSucess()方法

    Single.just(new Random().nextInt())
                    .subscribe(new SingleObserver<Integer>() {
                        @Override
                        public void onSubscribe(@NonNull Disposable d) {
    
                        }
    
                        @Override
                        public void onSuccess(@NonNull Integer integer) {
                            mRxOperatorsText.append("single : onSuccess : "+integer+"\n");
                            Log.e(TAG, "single : onSuccess : "+integer+"\n" );
                        }
    
                        @Override
                        public void onError(@NonNull Throwable e) {
                            mRxOperatorsText.append("single : onError : "+e.getMessage()+"\n");
                            Log.e(TAG, "single : onError : "+e.getMessage()+"\n");
                        }
                    });
    

    debounce

    去除发送频率过快,也就是自己设置时间过滤掉 该时间内的。


    image.png
    Observable.create(new ObservableOnSubscribe<Integer>() {
    
                @Override
                public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                    emitter.onNext(1); // skip
                    Thread.sleep(400);
                    emitter.onNext(2); // deliver
                    Thread.sleep(505);
                    emitter.onNext(3); // skip
                    Thread.sleep(100);
                    emitter.onNext(4); // deliver
                    Thread.sleep(605);
                    emitter.onNext(5); // deliver
                    Thread.sleep(510);
                    emitter.onComplete();
                }
            }).debounce(500,TimeUnit.MILLISECONDS).subscribe(new Observer<Integer>() {
                @Override
                public void onSubscribe(Disposable d) {
                    if (!d.isDisposed())
                    {
                        mTvName.append("连接-------\n");
                    }
                }
                @Override
                public void onNext(Integer integer) {
                   mTvName.append("接收到的值:"+integer+"\n");
                }
                @Override
                public void onError(Throwable e) {
                }
                @Override
                public void onComplete() {
                    mTvName.append("complete");
                }
            });
    
    image.png

    defer

    简单地时候就是每次订阅都会创建一个新的 Observable,并且如果没有被订阅,就不会产生新的 Observable。
    还不怎么理解他,不知实际用途是啥子,后面在研究,


    image.png
    Observable<String> ob = Observable.defer(new Callable<ObservableSource<String>>() {
                @Override
                public ObservableSource<String> call() throws Exception {
                    return Observable.just("A", "B", "C");
                }
            });
            ob.subscribe(new Observer<String>() {
                @Override
                public void onSubscribe(Disposable d) {
    
                }
    
                @Override
                public void onNext(String s) {
                    mTvName.append("defer"+s+"\n");
    
                }
    
                @Override
                public void onError(Throwable e) {
    
                }
    
                @Override
                public void onComplete() {
                    mTvName.append("complete");
                }
            });
    
    image.png

    last

    last操作符取出可观察的最后的一个值,或者满足某些条件的值

    image.png
    Observable.just(-2,3,-23,5).
                   filter(new Predicate<Integer>() {
                       @Override
                       public boolean test(Integer integer) throws Exception {
                           return integer<0;
                       }
                   }).last(0)
                   .subscribe(new Consumer<Integer>() {
                       @Override
                       public void accept(Integer integer) throws Exception {
                        mTvName.append("last"+integer);
                       }
                   });
    
    

    分析:当不使用 filter操作的时候,输出为 5,跟last中的值没关系,取最后一个。
    当使用filter操作的时候(小于0),只有 -2,-23,所有值为-23.跟last中的0无关

    merge

    作用吧多个Observable发射器 结合起来,接受可变参数,也支持迭代器集合、他和concat的区别在于,不用等到发射器A,发送完所有的的事件在进行发射器B的发送。
    实际中的应用就是一个界面如果同时请求多个接口数据的话,可以使用

     Observable<String> obA = Observable.create(new ObservableOnSubscribe<String>() {
    
                @Override
                public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                    emitter.onNext("A");
                    Thread.sleep(300);
                    emitter.onNext("B");
                    Thread.sleep(400);
                    emitter.onNext("C");
                    Thread.sleep(700);
                }
            });
            Observable.merge(obA,Observable.just("1","2","3"))
                    .subscribe(new Consumer<String>() {
                        @Override
                        public void accept(String s) throws Exception {
                         mTvName.append("接收顺序"+s+"\n");
                        }
                    });
    
    image.png

    reduce

    reduce操作符每次用用一个方法处理一个值

    Observable.just(1,2,3,4)
                   .reduce(new BiFunction<Integer, Integer, Integer>() {
                       @Override
                       public Integer apply(Integer integer, Integer integer2) throws Exception {
                           return integer*integer2;
                       }
                   }).subscribe(new Consumer<Integer>() {
               @Override
               public void accept(Integer integer) throws Exception {
                    mTvName.append(integer+"");
               }
           });
    

    分析 依次 1x2x3x4=24

    scan

    scan操作符作用和 reduce一致。区别reduce 只看结果,scan还会输出每一步。

     Observable.just(2,3,4,5)
                   .scan(new BiFunction<Integer, Integer, Integer>() {
                       @Override
                       public Integer apply(Integer integer, Integer integer2) throws Exception {
                           return integer*integer2;
                       }
                   }).subscribe(new Consumer<Integer>() {
               @Override
               public void accept(Integer integer) throws Exception {
                    mTvName.append(integer+""+"\n");
               }
           });
    

    输出:2,6,24,120

    window

    按照实际划分的窗口,将数据发送给不同的Obseverble发射器


    image.png
    Observable.interval(1,TimeUnit.SECONDS)
                  .take(15)
                  .window(3,TimeUnit.SECONDS)
                  .subscribeOn(Schedulers.io())
                  .observeOn(AndroidSchedulers.mainThread())
                  .subscribe(new Observer<Observable<Long>>() {
                      @Override
                      public void onSubscribe(Disposable d) {
    
                      }
                      @Override
                      public void onNext(Observable<Long> longObservable) {
                          mTvName.append("时间段到了,我要做事了\n");
                          longObservable.subscribeOn(Schedulers.io())
                                  .observeOn(AndroidSchedulers.mainThread())
                                  .subscribe(new Consumer<Long>() {
                                      @Override
                                      public void accept(Long aLong) throws Exception {
                                          mTvName.append("已经做完的事情:"+aLong+"\n");
                                      }
                                  });
    
    
                      }
    
                      @Override
                      public void onError(Throwable e) {
    
                      }
    
                      @Override
                      public void onComplete() {
                        mTvName.append("今天都过完了,我就做了上面的事情\n");
                      }
                  });
    
    image.png

    分析跟我预想的不一样,需要重新研究
    ===================华丽的分割线========================

    场景举例

    为了方便演示 rxjava的用法,使用Fast-Android-Networking作为网络请求,结合rxjava演示

    相关文章

      网友评论

          本文标题:Retrofit+rxjava学习记录

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