Retrofit+rxjava学习记录

参考文章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 getSearchBook(@Query("q") String name,@Query("tag") String tag1)  //name,tag由调入者传入
========等价
@GET("book/search?q=name&tag=tag1")
Call getSearchBook()  //name写死了
@QueryMap

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

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

用于替换url中的字段

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

POST请求

@Body

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

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

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

@Field

用于传输表单数据

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

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

@Header/@Headers

用于添加请求头部

eg:
@POST("user")
Call getUser(@Header("Authorization") String authorzation)
@Headers({
"Accpet:xxxxxxxxx",
"User-agent":xxxxxxxxxx"
})
@POST("user)
Call 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 map = new HashMap<>();
        map.put("q", "追风筝的人");
        map.put("tag", "");
        map.put("start", "0");
        map.put("count", "10");
        Call call = netApi.getSearchBook1(map);
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response 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 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() {
            @Override
            public void subscribe(ObservableEmitter 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() {
            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() {
            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
               emitter.onNext(1);
               emitter.onNext(2);
               emitter.onNext(4);
            }
        }).map(new Function() {
            @Override
            public String apply(Integer integer) throws Exception {
                int a=integer*2;
                return "生产出"+a;
            }
        }).subscribe(new Consumer() {
            @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 getManObservable()
    {
        return  Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter 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 getWomanObservable()
    {
        return  Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter 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() {
            @Override
            public String apply(String s, String s2) throws Exception {
                return s+"-配对了-"+s2+"\n";
            }
        }).subscribe(new Observer() {
            @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() {
                    @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() {
            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onNext(4);
            }
        }).flatMap(new Function>() {
            @Override
            public ObservableSource apply(Integer integer) throws Exception {
                List 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() {
                    @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() {
            @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() {
                    @Override
                    public boolean test(Integer integer) throws Exception {
                        return integer<5;
                    }
                })
                .subscribe(new Consumer() {
                    @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>() {
                    @Override
                    public void accept(List 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() {
                   @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() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                       mTvName.append("先保存下来"+integer+"\n");
                    }
                }).subscribe(new Consumer() {
            @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() {
                    @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() {

            @Override
            public void subscribe(ObservableEmitter 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() {
            @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 ob = Observable.defer(new Callable>() {
            @Override
            public ObservableSource call() throws Exception {
                return Observable.just("A", "B", "C");
            }
        });
        ob.subscribe(new Observer() {
            @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() {
                   @Override
                   public boolean test(Integer integer) throws Exception {
                       return integer<0;
                   }
               }).last(0)
               .subscribe(new Consumer() {
                   @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 obA = Observable.create(new ObservableOnSubscribe() {

            @Override
            public void subscribe(ObservableEmitter 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() {
                    @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() {
                   @Override
                   public Integer apply(Integer integer, Integer integer2) throws Exception {
                       return integer*integer2;
                   }
               }).subscribe(new Consumer() {
           @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() {
                   @Override
                   public Integer apply(Integer integer, Integer integer2) throws Exception {
                       return integer*integer2;
                   }
               }).subscribe(new Consumer() {
           @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>() {
                  @Override
                  public void onSubscribe(Disposable d) {

                  }
                  @Override
                  public void onNext(Observable longObservable) {
                      mTvName.append("时间段到了,我要做事了\n");
                      longObservable.subscribeOn(Schedulers.io())
                              .observeOn(AndroidSchedulers.mainThread())
                              .subscribe(new Consumer() {
                                  @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学习记录)