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<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演示

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • 引入依赖: implementation 'io.reactivex.rxjava2:rxandroid:2.0....
    为梦想战斗阅读 1,300评论 0 0
  • 一、Retrofit详解 ·Retrofit的官网地址为 : http://square.github.io/re...
    余生_d630阅读 1,832评论 0 5
  • 我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy阅读 5,462评论 7 62
  • 本篇文章介主要绍RxJava中操作符是以函数作为基本单位,与响应式编程作为结合使用的,对什么是操作、操作符都有哪些...
    嘎啦果安卓兽阅读 2,851评论 0 10
  • 转一篇文章 原地址:http://gank.io/post/560e15be2dca930e00da1083 前言...
    jack_hong阅读 910评论 0 2