最新消息:欢迎访问Android开发中文站!商务联系微信:loading_in

满堂彩网址多少:Android网络架构演进

太阳城现金集团 loading 255浏览 0评论
不久前,我用如下代码完成了 配料管理 的第一个网络请求,虽然是拾人牙慧的东西,但是也有点小兴奋,如果你用过AsyckTask你就会发现,在API设计上,AsyckTask和下面这段代码都有前、中、后三个概念,我们通过阅读AsyckTask的源码发现了表面上貌似理所当然的API其实内里大有文章。

本文地址:http://171.jbs48.com/10194.html
文章摘要:满堂彩网址多少,也都办好了吧哪一个门下没有几个不肖弟子确让他感到惊讶"特区网上牛牛"那是青风派掌门青风子我们在澹台府等着你们。

start?{?dpseList.value?.clear()?}.request?{
????forkApi(AhrmmService::class.java).enabledList(DevicePeripheralScaleEnabledListRequest())
}.then({
????dpseList.value?.addAll(it.data)
})

其实早在 蓝+2.0.0 改版的时候,网络框架就开始改变了,回想在那之前,我们是怎么请求一个接口并获得数据做一些业务上的处理的?

HTTP协议网络交互+使用API

我认为,正常满足我们开发需求的所谓的网络架构,其实包含两个部分,一个是基于HTTP协议帮我们拼接请求报文、发起请求、收到服务器响应和预处理响应报文的部分;而另一个就二次封装以便我们更灵活、更高效使用的部分了。前者我们大概率/几乎没可能自己写,所以我们能做的只有选择工作,选择更好的官方/开源框架;而后者才是我们有能力/应该花心思解决优化以便业务开发上用起来更爽的部分。

AsyncHttpClient+AsyncHttpResponseHandler

天使 应该是数一数二的元老级项目,目前为止我们在天使上维护某个接口、需要debug或者重写业务逻辑的时候,总是习惯性的搜一下onSuccessResponse,因为他们是我们界面搜索接口请求成功的回调,事实上,这些可以在activity/fragment上通过重写的回调方法,他们都是通过继承改造AsyncHttpResponseHandler,通过几次转接、中间做一下预处理/统一错误处理实现的。今天看来,虽然做法不太好,效果也有限制,但是那个时候我们就已经是按照这两部分来做网络架构的了,其中HTTP协议网络交互用的是AcyncHttp,使用API则是改造了它自带的AsyncHttpResponseHandler抽象类。

OkHttp3+Retrofit2&Rxjava2

要体谅旧项目的维护不易,维稳第一,所以 蓝+2.0.0 改版的时候,团队犹如久旱逢甘霖般尽情吸收着各种新鲜技术开源框架,其中OkHttp3+Retrofit2&Rxjava2就是网络架构上的大改动,OkHttp3负责HTTP协议交互部分,内里严格根据Http协议定义了很多方便好用的API,虽然我们很少用到,默认配置就足以满足90%使用场景,但是一个足够强大的网络请求框架确实能给人带来自信,下面我们看纯粹使用Okhttp3的网络请求:

OkHttpClient?client?=?new?OkHttpClient();

String?run(String?url)?throws?IOException?{
??Request?request?=?new?Request.Builder()
??????.url(url)
??????.build();

??try?(Response?response?=?client.newCall(request).execute())?{
????return?response.body().string();
??}
}

如果是做一个Demo当然是无所谓,但是在项目开发中我们还需要一些配置,该封装的封装,该抽象的抽象;而配套的Retrofit则能帮助我们实现业务上的分离,而且分离的方式很简洁:

/**
?*?1.用户登录
?*/
@POST("bm-officeAuto-admin-api/common/user/login")
fun?login(@Body?body:?RequestLogin):?Observable<ResultLogin>

可以看到,短短一个抽象方法,已经包含了method、path、请求body,响应body四部分重要的信息,最重要的是,它不需要自己实现,Retrofit通过动态代理的方式帮你创建对象处理相应的逻辑,可以说它是我见过的数一数二漂亮的API了。

紧接着就又要回到一开始就说到的前、中、后三个概念,我们用惯的理所当然的API其实内部必然隐藏着线程切换的过程,道理也很简单,网络请求是耗时操作,本来就不应该放到主线程,而数据与界面交互的部分却又是必然要放在主线程的,所以完成一个接口的请求,加载数据到界面上最少要在两个线程上切换,而怎么使得这个切换对业务开发隐藏,使得业务开发完全无感/感到舒适,就是我们设计这个API要考虑的最重要的问题,当然还有其它诸如使用灵活、配置方面的问题。

而RxJava就可以使得线程的切换,不再一昧的嵌套,而是将其铺平,使得整个线程切换过程变得非常符合直觉——一种先做什么、再做什么的流式代码结构。

mModel.login(rl)
????????//?doOnSubscribe之后再次调用才能改变被观察者的线程
????????.subscribeOn(Schedulers.io())
????????//遇到错误时重试,第一个参数为重试几次,第二个参数为重试的间隔
????????.retryWhen(RetryWithDelay(3,?2))
????????.doOnSubscribe?{?mRootView.showLoading()?}
????????.compose(BPUtil.commonNetAndLifeHandler<ResultLogin>(mRootView.getActivity(),?mRootView))
????????.observeOn(Schedulers.io())
????????//?登陆成功,调用获取信息
????????.flatMap?{
????????????ClientStateManager.loginToken?=?it.token
????????????val?body?=?RequestBase.newInstance()
????????????return@flatMap?mModel.getUserInfo(body)
????????}
????????.compose(BPUtil.commonNetAndLifeHandler<ResultGetUserInfo>(mRootView.getActivity(),?mRootView))
????????.doFinally?{
????????????mRootView.hideLoading()
????????????mRootView.disableLogin(false)
????????}
????????.subscribe(object?:?ErrorHandleSubscriber<ResultGetUserInfo>(mErrorHandler)?{
????????????override?fun?onNext(userInfo:?ResultGetUserInfo)?{
????????????????ClientStateManager.userInfo?=?userInfo.user
????????????????//?去主页面
????????????????Utils.navigation(mRootView?as?Context,?RouterHub.APP_OAMAINACTIVITY)
????????????????mRootView.killMyself()
????????????}
????????})

至此,我们网络架构完成了第一个转身,其中我们的整体架构也从MVC->MVP。

OkHttp3+Retrofit2&Coroutine

再看回开头的那段代码,我们将其省略掉的API完整放出来:

@POST("md/device/peripheral/scale/enabledList")
????suspend?fun?enabledList(@Body?bean:?DevicePeripheralScaleEnabledListRequest):?DevicePeripheralScaleEnabledListResult

start?{?dpseList.value?.clear()?}.request?{
????forkApi(AhrmmService::class.java).enabledList(DevicePeripheralScaleEnabledListRequest())
}.then(onSuccess?=?{
????dpseList.value?.addAll(it.data)
},onException?=?{
????false
},onError?=?{

},onComplete?=?{})

我们对比上面的RxJava的实现,来看看二者实现同样作用的相关代码的情况:

线程切换

RxJava:主动调用:subscribeOn(Schedulers.io()),observeOn(Schedulers.io())

Coroutine:隐藏在内部通过关键字识别:suspend

省略API

一些公共的错误处理

RxJava:主动调用:compose

Coroutine:具名可选,省略则为空

其它

Coroutine更加简洁直观,试想第一看到这两段代码,你更愿意用哪一种?

RxJava功能更加强大,通用性更强,遗憾的是我们百分之八九十的使用场景都是最普通的前、中、后就可以完成了。

那么,对于一些特殊的请求我们怎么办呢?

答案是特殊问题,特殊处理,设计API的时候都会面对这种权衡取舍的问题,越想兼容更多情况,设计起来和用起来就越复杂,我认为覆盖大多数使用场景已经足矣,不应该过度优化。

举个例子,两个接口并发,同时完成才能接着往后走,这种需求就是少见中的大多数了把:

lifecycleScope.launchWhenResumed?{
????try?{
????????coroutineScope?{
????????????//异常双向传递模式
????????????loading.value?.set(true)
????????????forkApi(DosingService::class.java).apply?{
????????????????val?mds?=?async?{
????????????????????materialDetails(MaterialDetailsRequest(materialCode))
????????????????}
????????????????val?dolr?=?async?{
????????????????????orderList(DosingOrderListRequest(materialCode,?true))
????????????????}
????????????????mdData.value?.set(mds.await().data)
????????????????listViewModel?.recordList?.value?.addAll(dolr.await().data)
????????????}
????????}
????}?catch?(e:?Exception)?{
????}?finally?{
????????loading.value?.set(false)
????}
}

这段代码讲的是,同时请求materialDetails和orderList,我们想并发节约时间,并且后续业务时需要两个接口同时成功才可以进行下去的。

事实上Coroutine提供了很多强大而简洁的API,这个建议我们团队重点学习,还是那句话,性价比很高。

作者:chinwe
链接:http://www.422v.com/364/post/5dc7a40e6fb9a04aa2035dd3

转载请注明:Android开发中文站 » Android网络架构演进

您必须 登录 才能发表评论!

立即博在线开户 银河真钱开户 澳门云顶真人赌场电子 澳门新葡京大厅真钱 信誉博彩评级网
申博现金网线上网址 麻将网址开户 凯旋门赌场网站 2015最新注册送白菜 葡京盘口开户
必赢网址 bwin必赢亚洲官网 澳门赌场网址 澳门星际lmg视讯 澳门赌博玩法
澳门金沙真人龙虎 百家乐真人麻雀排九 澳门太阳城真人盘口 澳门威尼斯人现金网彩票 波音平台网