参考文章1:Android 教你一步步搭建MVP+Retrofit+RxJava网络请求框架
Retrofit的认识
测试网址
https://api.douban.com/v2/book/search?q=金瓶梅&tag=&start=0&count=1
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.pngObservable.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
操作符取出可观察的最后的一个值,或者满足某些条件的值
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演示
网友评论