java 协程 http_RxJava也能像协程那样优雅的请求网络

RxJava也能像协程那样优雅的请求网络

Retrofit&Coroutines 与 Retrofit&RxJava

两年没写过文章了,一时之间不知道说些什么好…哔…

网络请求框架相信在座的各位都能巴拉巴拉的说出一大堆,但是,我今天要说的不是网络请求框架,今天就来说说被大家吹捧的协程以及比大家抛弃的RxJava的区别吧,以及RxJava到底能不能像协程那样方便快捷。

本篇基于Retrofit2.9.0进行,与之前版本的请求方式略有差别,请注意。

一、创建Retrofit

第一步,Retrofit的配置

object RetrofitManager {

fun create(clazz: Class) : K = getRetrofit().create(clazz)

private fun getRetrofit(): Retrofit {

// 获取retrofit的实例

return Retrofit.Builder()

//url必须以 ‘/’ 结尾,不然会报IllegalArgumentException

.baseUrl(ApiService.BASE_URL)

.client(getOkHttpClient())

.addCallAdapterFactory(RxJava2CallAdapterFactory.create())

.addConverterFactory(GsonConverterFactory.create())

.build()

}

private fun getOkHttpClient(): OkHttpClient {

//添加一个log拦截器,打印所有的log

val httpLoggingInterceptor = HttpLoggingInterceptor()

//可以设置请求过滤的水平,body,basic,headers

httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY

return OkHttpClient.Builder()

.addInterceptor(httpLoggingInterceptor) //日志,所有的请求响应度看到

.connectTimeout(15L, TimeUnit.SECONDS)

.readTimeout(15L, TimeUnit.SECONDS)

.writeTimeout(15L, TimeUnit.SECONDS)

.proxy(Proxy.NO_PROXY)

.build()

}

}

二、创建Service接口

本次演示所用的接口来源与 玩android

interface ApiService {

companion object{

const val BASE_URL = "https://www.wanandroid.com/"

}

@GET("article/list/{page}/json")

fun getList(

@Path("page") page: Int

) : Observable

@GET("banner/json")

fun getBannerList(): Call

@POST("postxxx/xxx")

fun postMsg(@Body json : RequestBody) : Observable

}

好了,我们先回顾下传统的RxJava+Retrofit进行的网络请求。

首先对RxJava进行封装,虽然可能和你们封装的不同但也大同小异。

fun request(){

check: Boolean = true,

function: Function>,

next: Consumer,

error: Consumer = Consumer {

finishRefreshorLoadData = true

errorLiveData.postValue(it)

}

) {

val disposable = Observable.just(check)

.subscribeOn(Schedulers.io())

.unsubscribeOn(Schedulers.io())

.filter { t -> t }

.flatMap(function)

.observeOn(AndroidSchedulers.mainThread())

.subscribe(next, error)

addSubscription(disposable)

}

然后请求可能是这样

request(

function = Function>{

//网络请求

model.getList(1)

},

next = Consumer{

liveDataVideo.postValue(it)

}

)

没了解协程之前,这样乍看也没什么毛病,中规中矩的,就是不够简便。

再看看协程的网络请求:

GlobalScope.launch {

val bean = model.getBannerList().await()

liveData.postValue(bean)

}

吸(猛的倒吸吸一口气)。

因为Retrofit是2.9版本的,协程直接封装在Retrofit的内部,作为开发者的我们并不需要去过多的封装,直接就可以进行调用。

两者对比,孰优孰劣一目了然。协程既然能做到这么简便,那RxJava可不可以呢?

三、RxJava重封装

肯定可以啦。

首先我们来分析下网络请求我们所关心的部分:

1.直接处理请求成功结果

2.不关心请求异常

3.界面销毁取消现有的请求

最终封如下,由扩展函数实现

fun Observable.onResult(

next : (T) -> Unit

){

this onResult Consumer {

//这里进行返回判断,与后台协定

if (!TextUtils.equals(it.errorCode,"200")){

errorLiveData.value = it.errorMsg

return@Consumer

}

next(it)

}

}

看看最终的使用结果

fun getList(){

//RxJava

model.getList(0).onResult {

//做点其他的事情

//省略其他逻辑代码

liveData2.value = it

}

}

fun getBannerList(){

//协程

GlobalScope.launch {

val bean = model.getBannerList().await()

liveData.postValue(bean)

}

}

嗯,这就很完美了。如果你的数据请求回调除了post数据之外,没有其他的操作那还可以更加的简单点:

fun getList(){

//RxJava

//没有其他逻辑,直接返回数据

model.getList(0).onResult(liveData2::setValue)

}

协程虽然在网络请求有独特之处可以替换RxJava,但RxJava的流式编程也不是协程所能替代的,孰优孰劣难以定义。不知道你喜欢那种呢。 4b8f0394127dcc2ebfdab274ae6a54db.png

结尾附上RxJava的封装代码(Kotlin)

open class BaseViewModel : ViewModel(),IViewModel {

val errorLiveData: MutableLiveData = MutableLiveData()

private var compositeDisposable = CompositeDisposable()

override fun onCreate(owner: LifecycleOwner) {

//创建

}

override fun onDestroy(owner: LifecycleOwner) {

//销毁

detachView()

//移除生命周期监听观察者

owner.lifecycle.removeObserver(this)

}

override fun onLifecycleChanged(owner: LifecycleOwner, event: Lifecycle.Event) {

//生命周期状态改变

}

//泛型可以为 ,也可以为 >

//此处为Observable的拓展函数,你也可以改为Flowable的拓展函数

fun Observable.onResult(

next: Consumer,

error: Consumer = Consumer {

errorLiveData.postValue(it.message)

}

) {

val disposable = this.subscribeOn(Schedulers.io())

.unsubscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(next, error)

addSubscription(disposable)

}

private infix fun Observable.onResult(

next: Consumer

) {

this.onResult(next,Consumer {

errorLiveData.postValue(it.message)

})

}

fun Observable.onResult(

next : (T) -> Unit

){

this onResult Consumer {

//这里进行返回判断

/*if (!TextUtils.equals(it.errorCode,"200")){

errorLiveData.value = it.errorMsg

return@Consumer

}*/

next(it)

}

}

private fun addSubscription(disposable: Disposable) {

compositeDisposable.add(disposable)

}

private fun detachView() {

//保证activity结束时取消所有正在执行的订阅

if (!compositeDisposable.isDisposed) {

compositeDisposable.clear()

}

}

}

Java版

某同学:虽然你说的很好,但是我用的是Java哦,Java有没有办法实现呢?

博主:额。。。这。。。

先看看kotlin的拓展方法转成Java是什么样子的,大概如下:

6bb621fa82c0295308a1ad44db553376.png

514f5daa7553bb3153c9104271791020.png

由此可以看出:

kotlin: (Class)类.Function() 等价于

java的 Function(对象)

等式:Class.(参数…,Function…) ==> Function(对象,参数…,Function…)

所以,以上的代码都可以转换成这样

//Java版

public class BaseViewModel extends ViewModel implements IViewModel {

public boolean finishRefreshorLoadData = true;

public MutableLiveData errorLiveData = new MutableLiveData<>();

private CompositeDisposable compositeDisposable = new CompositeDisposable();

@Override

public void onCreate(@NotNull LifecycleOwner owner) {

}

@Override

public void onDestroy(@NotNull LifecycleOwner owner) {

detachView();

owner.getLifecycle().removeObserver(this);

}

@Override

public void onLifecycleChanged(@NotNull LifecycleOwner owner, @NotNull Lifecycle.Event event) {

}

public void onResult(

Observable observable,

Consumer next,

Consumer error

){

Disposable disposable = observable.subscribeOn(Schedulers.io())

.unsubscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(next, error);

compositeDisposable.add(disposable);

}

public void onResult(

Observable observable,

Consumer next

){

onResult(observable,next,throwable -> {

errorLiveData.postValue(throwable);

});

}

private void detachView() {

//保证activity结束时取消所有正在执行的订阅

if (!compositeDisposable.isDisposed()) {

compositeDisposable.clear();

}

}

}

具体引用如下:

public class JavaViewModel extends BaseViewModel{

private MainModel model = new MainModel();

public MutableLiveData liveData = new MutableLiveData<>();

public void getList(){

onResult(model.getList(0),homeListBean -> {

//做点其他事情

liveData.setValue(homeListBean);

});

//没有其他操作,直接放回数据

onResult(model.getList(0),liveData::setValue);

}

}

某同学:看起来好像没kotlin方便哦。

我:。。。1b1706930894a541fcb29f1a11f321ab.png

项目地址

因为篇幅所限,本文只说RxJava的封装,详细代码就不贴出来了,附上demo的地址,有兴趣的可以去看看。

github: https://github.com/cithrf/RxDemo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值