求大神给点优化意见 虽然写的不怎么样😁但是还是想求几个 star
1
hongch OP 谢谢各位大佬的 star
|
2
hongch OP # 历时 2 天,完成了用 kotlin 写网络框架
## 1.错误统一处理</br> ## 2.和服务端约定 response 格式,剥离出 data</br> ## 3.MVVM</br> ## 4.DTO-VO 转换</br> ## 5.Activity 层几乎没有代码,极度简洁</br> --- #先上效果图 </br> 1 )首先新建一个 VM 类,用于网络请求</br> ``` class MainVM { fun getData(callback: DesCallBack<HCVO>) { return ApiClient .instance .getApiService() .test() .compose(RxStreamHelper().io_Main()) .map { it.transform() } .subscribe(Destiny(callback)) } } ``` </br> 2 )利用 map 操作符将 DTO 转为业务所需的 VO </br> ``` .map { it.transform() } ``` 3 )然后通过 callback 的方式将 data 暴露给 activity,具体业务场景不同,有时候可能需要 Observer 的 complete</br> 4 )最后调用 VM 的方法可以看到 View 层只有几行代码,极大程度降低了业务与逻辑的冗余度,</br> ``` fun request() { val mainVM = MainVM() mainVM.getData(object : DesCallBack<HCVO> { override fun success(any: HCVO) { Log.i("success", any.name) } override fun failed(e: Throwable) { } }) } ``` </br> 如果用上 databinding Activity 只需要请求网络就可以了 是不是很方便? --- # 具体实现</br> ## 一、Retrofit 的封装</br> kotloin 对于 coder 来说,简化了大量代码,双重检查单例只需要一行代码</br> ``` val instance: ApiClientby lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED){ ApiClient() } ``` </br> 这样就保证了全局只有一个 retrofit 对象 </br> 接口层没什么变化,不过是 kotlin 的语法不一样 这样就完成了 retrofit 的封装 --- ## 二、服务端返回的数据处理</br> ### 1 )首先定义一个基础类型,这里是服务端返回的格式,分别为 code,msg,和 data,在后期我们要将 data 单独剥离出来给具体的业务使用,code 和 msg 与业务无关 ``` open class BaseModel<T> { var code: Int? = null var msg: String? = null var data: T? = null } ``` ### 2 )错误处理,错误分为服务端错误和本地错误</br> 1.本地错误:在 onErrorResumeNext()的时候返回自定义的 exception,通过 Observable.error()发射出去</br> 具体的 CustomException 如图所示,判断 throwable 类型,自定义的 exception</br> ``` class CustomException { companion object { fun handleException(e: Throwable): ApiException { if (e is HttpException) { var ex = ApiException(e.code(), e.message(), e) when (ex.code) { UNAUTHORIZED -> ex.msg("未授权的请求") FORBIDDEN -> ex.msg("禁止访问") NOT_FOUND -> ex.msg("服务器地址未找到") REQUEST_TIMEOUT -> ex.msg("请求超时") GATEWAY_TIMEOUT -> ex.msg("网关响应超时") INTERNAL_SERVER_ERROR -> { ex.msg("服务器出错") ex.msg("无效的请求") } BAD_GATEWAY -> ex.msg("无效的请求") SERVICE_UNAVAILABLE -> ex.msg("服务器不可用") ACCESS_DENIED -> ex.msg("网络错误") HANDEL_ERROR -> ex.msg("接口处理失败") else -> { if (TextUtils.isEmpty(ex.msg)) { ex.msg(e.message!!) } if (TextUtils.isEmpty(ex.msg) && e.getLocalizedMessage() != null) { ex.msg(e.getLocalizedMessage()) } if (TextUtils.isEmpty(ex.msg)) { ex.msg("未知错误") } } } return ex } else if (e is JSONException || e is ParseException) { var ex = ApiException(PARSE_ERROR, e.message, e) ex.msg("解析错误") return ex } else if (e is ConnectException) { var ex = ApiException(NETWORK_ERROR, e.message, e) ex.msg("连接失败") return ex } else if (e is javax.net.ssl.SSLHandshakeException) { var ex = ApiException(SSL_ERROR, e.message, e) ex.msg("证书验证失败") return ex } else if (e is java.security.cert.CertPathValidatorException) { var ex = ApiException(SSL_NOT_FOUND, e.message, e) ex.msg("证书路径没找到") return ex } else if (e is SSLPeerUnverifiedException) { var ex = ApiException(SSL_NOT_FOUND, e.message, e) ex.msg("无有效的 SSL 证书") return ex } else if (e is ConnectTimeoutException) { var ex = ApiException(TIMEOUT_ERROR, e.message, e) ex.msg("连接超时") return ex } else if (e is java.net.SocketTimeoutException) { var ex = ApiException(TIMEOUT_ERROR, e.message, e) ex.msg("连接超时") return ex } else if (e is java.lang.ClassCastException) { var ex = ApiException(FORMAT_ERROR, e.message, e) ex.msg("类型转换出错") return ex } else if (e is NullPointerException) { var ex = ApiException(NULL, e.message, e) ex.msg("数据有空") return ex } else if (e is FormatException) { var ex = ApiException(-200, e.message, e) ex.msg("服务端返回数据格式异常") return ex } else if (e is UnknownHostException) { var ex = ApiException(NOT_FOUND, e.message, e) ex.msg("服务器地址未找到,请检查网络或 Url") return ex } else { var ex = ApiException(UNKNOWN, e.message, e) ex.msg("未知异常") return ex } } } } ``` ### 3 )数据剥离,用到了 flatMap,此处解析服务端有关的错误,如果 code 等于 200,则代表接口请求成功,否则通过 Observable.error()抛出</br> ``` .flatMap { tBaseModel -> if (tBaseModel.code == 200) { Observable.just(tBaseModel.data!!) } else Observable.error(ApiException(tBaseModel.code!!, tBaseModel.msg!!)) } ``` ### 4 )线程调度,在子线程请求,在主线程处理</br> ``` upstream . subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) ``` 通过 4 个操作符之后我们完成了以上任务,最后通过 compose 操作将这个操作集合合并为一个简化代码 github 地址: https://github.com/honglvt/NetWorkUtil |
3
kazeik 2018-08-24 09:24:12 +08:00
藕合性太强。没有自定义的 callback.
|
4
shangshicc 2018-08-27 17:55:40 +08:00
建议修改标题为自己对第三方框架的封装,表示刚看这个标题后以为你自己写了一个类似 okhttp 的库
|
5
hongch OP - -
|
6
Fit7z 2018-09-03 15:09:25 +08:00
这只是常规操作,请坐下
|