Retrofit是对OkHttp网络库的封装,真正的网络请求是通过OkHttp完成的
Retrofit主要用到了适配器模式
使用Retrofit五个步骤:
class Person {
String name;
int age;
int id;
}
public interface retrofit_interface {
@GET("/course_api/wares/hot")
Call getCall(@Query("pageSize") int pageSize, @Query("curPage")int curPage);
}
public class RetrofitDemo {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.sina.com/") //设置网络请求基地址
.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器
.addCallAdapterFactory(DefaultCallAdapterFactory.create()) //设置网络适配器
.build();
//创建网络请求接口对象
retrofit_interface request = retrofit.create(retrofit_interface.class);
//配置网络请求参数,并获取Call对象
Call call = request.getCall(1, 10);
public void callRequest() {
//发送网络请求(异步)
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
//对返回数据进行处理
response.body().name;
}
@Override
public void onFailure(Call call, Throwable throwable) {
System.out.println("连接失败");
}
});
}
}
//Post中用到的Request为wire生成的Pb文件,并对Retrofit做了封装
val retrofit = Retrofit.Builder()
.setEndpoint(buildUrl())
.client { SsRetrofitClient() }
.addInterceptor(SsInterceptor())
.addInterceptor(ClassroomInterceptor())
.httpExecutor(SsHttpExecutor())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())
.addConverterFactory(WireConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
interface IGetNameApi {
companion object {
fun getNameApi(): IGetNameApi {
return Classroom.context().retrofit.of(IGetNameApi::class.java)
}
}
@POST("/tools/name/v1/user_name/")
@Retry(2)
fun getName(@Body request: GetNameRequest): Observable
}
源码分析的七个要点:
通过RxJavaCallAdapter和Retrofit实现网络请求
//通过Retrofit发送网络请求
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fy.iciba.com/") // 设置网络请求URL
.addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //支持RxJava
.build();
//创建网络请求接口的实例
LoopRequest_interface request = retrofit.create(LoopRequest_interface.class);
//采用Observable<...>形式对网络请求进行封装
Observable observable = request.getCall();
//通过线程切换发送网络请求
observable.subscribeOn(Schedulers.io()) //切换到IO线程进行网络请求
.observeOn(Schedulers.newThread()) //切换回到主线程处理请求结果
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Person result) {
//接收服务器返回的数据
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
Retrofit(OkHttp包装类) Interceptor经典用法:Passport Sdk会提供TTTokenInterceptor,用于自动处理request和response,用于从response中提取鉴权信息并在header中添加身份鉴权信息
RxJava(轻量级框架<1M),采用响应式编程,扩展了传统的观察者模式,让异步编程变的更加简洁。RxJava拥有丰富的操作符,通过Scheduler(调度器)可以很方便的实现线程切换(observeOn、subscribeOn)
观察者模式:Observable、Observer、subscribe、Event
观察者模式扩展:onNext、(onCompleted、onError)
RxAndroid是RxJava针对Android平台的扩展库
操作符分类:创建操作符、转换操作符、过滤操作符、组合操作符、错误处理操作符
创建型操作符:Create(原始)、Just(创建单一值对象)、From(发射数组或列表型对象)、Defer(延迟创建、每次订阅会创建新的Observable)、Empty(创建空的Observable,会调用onComplete、onError)、Never(创建空的永不停止的Observable)、Throw(创建一个空的但最终会发生错误的Observable)、Interval(定时发送,整数从0到无穷递增)、Range(发送一定范围内的值)、Repeat(指定重复发送的次数)
转换操作符:Map(数据转换)、FlatMap(平铺,和Map的区别并不是可以返回Observable,Map也可以返回Observable,区别在于FlapMap只能返回Observable且转换函数更灵活)、GroupBy(分组)、Buffer(聚集,分批次发送)、Window(和Buffer类似,也是聚集作用,只不过返回的是Observable对象,而Buffer直接返回数据集合)、Scan(扫描求和)
过滤型操作符:Debounce(数据产生后,超过指定时间间隔没有新数据产生,则发送当前数据)、Distinct(去重)、ElementAt(取指定位置数据)、Filter(可指定过滤规则,比如发射的整数要大于0)、First(取第一个数据)、Last(取结尾数据)、IgnoreElements(忽略所有数据,只发送结束或错误)、Sample(每隔一段时间取样发射)、Skip(跳过前几项数据)、SkipLast(跳过后几项数据)、Take(取前几项数据)、TakeLast(取后几项数据)
组合操作符:Zip(两个数据源的数据项通过指定方法进行合并,其中一个结束或异常,另外一个也终止发射)、Merge(两个数据源的数据项按照时间顺序合并成一个新的数据流)、StartWith(在数据源之前插入数据)、CombineLatest(CombineLatest操作符类似于zip,但是只有当原始Observable中的每一个都发射了一条数据时zip才发射数据,而CombineLatest则是当原始的Observable中任意一个发射了数据时就发射一条数据。当原始Observables的任何一个发射了一条数据时,CombineLatest使用一个函数结合它们最近发射的数据,然后发射这个函数的返回值)
错误处理操作符:onErrorReturn(遇到错误返回特定值)、onErrorResumeNext(遇到错误继续,订阅者无法捕获错误信息)、onExceptionResumeNext(遇到错误继续,订阅者可以捕获错误信息)
Schedule第二版理解(简单看了代码):
Observable.just(1)
.subscribeOn(Schedulers.io())
.map {i ->
Log.e("zzzz", "mapThread ${android.os.Process.myTid()} $i")
i + 1
}
.observeOn(Schedulers.io())
.map {i ->
Log.e("zzzz", "mapThread ${android.os.Process.myTid()} $i")
i + 1
}
.subscribeOn(Schedulers.io())
.subscribe({
Log.e("zzzz", "observerThread ${android.os.Process.myTid()} $it")
}, {
Log.e("zzzz", "observerThread ${android.os.Process.myTid()} $it")
})
Observable.subscribeOn:生成ObservableSubscribeOn,内部subscribe调用subscribeActual,scheduler切换线程并执行SubscribeTask(执行source.subscribe(parent)),source代表上层的Observable。parent是封装好的SubscribeOnObserver,SubscribeOnObserver是封装了Observer,并没有其他额外操作
Observable.observeOn:生成ObservableObserverOn,内部subscribe调用subscribeActual,scheduler直接调用source.subscribe(parent),并没有进行线程切换。parent是封装好的ObserveOnObserver,内部onNext、onComplete、onError方法会切换线程
Observable.map:生成ObservableMap,内部subscribe调用subscribeActual,scheduler直接调用source的相关方法,并没有其他额外操作。parent是封装好的MapObserver,内部onNext、onComplete、onError方法会直接执行map-function,然后也不会切换线程
总结一下:subscribe调用之后,一路向上调用observable.subscribe,如果遇到ObservableSubscribeOn,执行subscribe时会切换线程,并且一路上会封装observer,默认什么都不操作(map、observerOn除外)
基本原理:
@Override
public void subscribeActual(final Observer super T> s) {
final SubscribeOnObserver parent = new SubscribeOnObserver(s);
s.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver parent;
SubscribeTask(SubscribeOnObserver parent) {
this.parent = parent;
}
@Override
public void run() {
source.subscribe(parent);
}
}
https://www.jianshu.com/p/59c3d6bb6a6b
https://www.jianshu.com/p/4e78d447394e
observeOn作用于该操作符之后的操作符直到出现新的observeOn操作符
subscribeOn作用于该操作符之前的Observable的创建操符作以及doOnSubscribe 操作符 ,换句话说就是doOnSubscribe以及Observable的创建操作符总是被其之后最近的subscribeOn控制
Observable.create(observableOnSubscribe)
.subscribeOn(Schedulers.io())
.map {
i -> i + "哈哈"
Log.e("zzzz", "${android.os.Process.myTid()} $i")
}
// .subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe({
Log.e("zzzz", "observerThread ${android.os.Process.myTid()} $it")
}, {
Log.e("zzzz", "observerThread ${android.os.Process.myTid()} $it")
})
2019-09-19 14:50:32.407 17390-17390/com.example.rxjava2 E/zzzz: mainThread 17390
2019-09-19 14:50:32.481 17390-17416/com.example.rxjava2 E/zzzz: subscribeThread 17416
2019-09-19 14:50:32.481 17390-17416/com.example.rxjava2 E/zzzz: 17416 1
2019-09-19 14:50:32.481 17390-17416/com.example.rxjava2 E/zzzz: 17416 2
2019-09-19 14:50:32.482 17390-17418/com.example.rxjava2 E/zzzz: observerThread 17418 14
2019-09-19 14:50:32.482 17390-17418/com.example.rxjava2 E/zzzz: observerThread 17418 14
上面补充了一个用例,细想一下没有那么简单,subscribeOn也可以控制下面(没有observeOn的情况)
RxJava发射器类型:Observable、Flowable、Single、Completable、Maybe
val result = Maybe.create(MaybeOnSubscribe { e ->
e.onSuccess("testA")
e.onComplete()
}).subscribe({ println("Maybe $it") },
{ println("Maybe onError") },
{ println("Maybe onComplete") }
)
类型 |
描述 |
Observable |
能够发射0或n个数据,并以成功或错误事件终止(onNext、onComplete、onError) |
Flowable |
能够发射0或n个数据,并以成功或错误事件终止;支持Backpressure,可以控制数据源发射的速度 |
Single |
只发射单个数据或错误事件(onSuccess、onError) |
Completable |
不发射数据,只处理onComplete和onError事件(onComplete、onError) |
Maybe |
能够发射0或1个数据,要么成功,要么失败((onSuccess、onComplete)互斥关系、onError) |