网络框架封装(retrofit2+rxjava2+okhttp3)
Posted 夜尽天明89
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络框架封装(retrofit2+rxjava2+okhttp3)相关的知识,希望对你有一定的参考价值。
后面的 项目说明 ,请仔细看。如果自己的项目有需要扩展的,也好知道去哪里改
写在前面:项目中隐去了所有接口、有效参数,如果要验证,请自己找合适的接口验证
改封装支持的功能有:
1、接口请求;
2、addHeader相关;
3、请求接口的参数获取(并排序),便于处理(如:加密,和后台校验)
4、接口相关日志打印
为了方便使用,直接写成 library ,复制拿走就行
引用 library ,注意2个地方:
1、app中的gradle,dependencies 中添加
//netlib 是我网络封装的library的名字,如果不想用这个,自己新建个,把我里面的代码全复制过去
implementation project(':netlib')
2、整个工程的 settings.gradle
rootProject.name='MyNetDemo'
include ':app'
include ':netlib' //加这行。还有其他写法,这是我新建后自动生成的,就没管
项目结构图:
项目说明: 很重要
1、注意 BaseBeanData 的格式
BaseBeanData<T>(var msg: String, var code: String, var data: T)
项目中的所有接口,返回的数据格式,都应该规范为
BaseBean(状态描述、状态码、数据bean) 这种。
如果和自己项目中的不一致,做对应修改
2、ResultFunc 中,对返回的总数据做了处理,只拿出来了 data,如果在处理接口请求结果的时候,需要用到 msg、code,就不用这个。下面会有示例说明
3、ApiService 中,存放了所有接口,用的时候,删了demo中的,替换成自己项目的就行
4、ApiServiceImpl 中,存放了所有接口的请求动作。用的时候,删了demo中的,替换成自己项目的就行
5、如果要给每个接口都在header上添加信息,在 NetApiFactory 中
//添加header
builder.addInterceptor(object : Interceptor
......
)
6、如果项目中有需要,要求拿出来请求的参数,做处理(如:加密),然后添加到header里 用于后台的合法性校验。在 NetApiFactory 中
/**
* 获取参数。如果想的话,其实可以和 添加header一起处理,这里为了方便区分,就分开写了
*
* 这里的作用,是获取请求的参数,以便于对参数进行处理。如:对参数进行一定规则的加密,用于后台校验
*
* 如果项目中用不到参数处理,可以注释这些代码
*
* 根据项目需求,自行扩展
*
* 这里是对参数的key,进行了字母顺序排序,然后用特殊符号拼接
* 示例:abc=abc&mobile=123123&nnnqqq=nnnqqq&pwd=a1234567
*/
builder.addInterceptor(object : Interceptor
......
)
7、baseUrl 的设置在 Url 文件中
8、为了在 android Studio 控制台上打印日志,加个了个 LoggingInterceptor
日志效果是:
接下来,利用代码,进行讲解。留意注释
1、在MainActivity 的 onCreate中,直接调用一个接口(获取分享信息),模拟的情况是,APP刚启动,在闪屏页(欢迎页等)请求广告接口,且这个接口无参数
MainActivity - onCreate - toGetShareData()
data class MineShareBean(
var title: String = "",
var content: String = "",
var pic: String = "",
var url: String = ""
)
//----------------------------------
//获取分享数据。这个方法在 ApiServiceImpl 中
fun getMineShareInfo(observer: ApiBaseObserver<MineShareBean>)
apiZmService.getMineShareInfo()
.compose(RxBiz.transformMain())
.map(ResultFunc<MineShareBean>())//假设接口处理那里,不需要关系code值,只要具体内容
.onErrorReturnItem(MineShareBean())//这里是为了避免接口返回的bean是null而报错
.subscribe(observer)
//---------------------------------------------
ApiServiceImpl.getMineShareInfo(
object : ApiBaseObserver<MineShareBean>()
override fun onNext(t: MineShareBean)
/**
* 日志示例
* MineShareBean(
* title=...,
* content=...,
* pic=...,
* url=...
* )
*/
LogUtil.e("$t")
override fun onError(throwable: Throwable)
super.onError(throwable)
)
这个时候,接口的header打印出来有:
UserID: 1234567890
UserName: abcdefg
VersionName: 1.0
2、点击按钮“获取分享数据(GET、带参数)”
//获取分享数据,带参数
fun getMineShareInfo2(
page: String,
pageSize: String,
ddd: String,
pageA: String,
temp: Int,
observer: ApiBaseObserver<MineShareBean>)
apiZmService.getMineShareInfo2(page,pageSize,ddd,pageA,temp)
.compose(RxBiz.transformMain())
.map(ResultFunc<MineShareBean>())
.onErrorReturnItem(MineShareBean())
.subscribe(observer)
//-----------------------------------------
//用于模拟带参数的get请求
ApiServiceImpl.getMineShareInfo2(
"page", "pageSize", "ddd", "pageA", 123,
object : ApiBaseObserver<MineShareBean>()
override fun onNext(t: MineShareBean)
override fun onError(throwable: Throwable)
super.onError(throwable)
)
现在,header变成了。注意添加参数的顺序、header中参数的顺序。header中是经过排序的
UserID: 1234567890
UserName: abcdefg
VersionName: 1.0
JiaoYanStr: ddd=ddd&page=page&pageA=pageA&pageSize=pageSize&temp=123
3、接下来用讲解post方法,post方法 我用了 表单提交、非表单提交两种。因为,在获取接口参数内容的时候,需要区分表单和非表单
3.1、POST 表单提交
/**
* 手机号,密码登陆。表单提交
*/
@FormUrlEncoded
@POST("abc/abc")
fun toMobilePwdLogin(@FieldMap params: HashMap<String, String>): Observable<BaseBeanData<PhonePwdLoginBean>>
//------------------------------------------
/**
* 手机号、密码登陆。表单提交
*
* 注意:这里没有单独拿出来 PhonePwdLoginBean,而是把返回的数据,全部返回了。是因为登录那里,要用code值来判断登录是否成功
*/
fun toMobilePwdLogin(
paramsMap: HashMap<String, String>,
observer: ApiBaseObserver<BaseBeanData<PhonePwdLoginBean>>)
apiZmService.toMobilePwdLogin(paramsMap)
.compose(RxBiz.transformMain())//和上面对比,没有ResultFunc,因为接口结果处理那里,要用到code
.subscribe(observer)
//---------------------------------------
val paramsMap = HashMap<String, String>()
//手机号
paramsMap["mobile"] = "123123"
//密码
paramsMap["pwd"] = "a1234567"
//下面2个参数,是额外随便加的,就是单纯为了看参数排序的
paramsMap["abc"] = "abc"
paramsMap["nnnqqq"] = "nnnqqq"
ApiServiceImpl.toMobilePwdLogin(
paramsMap,
object : ApiBaseObserver<BaseBeanData<PhonePwdLoginBean>>()
override fun onNext(t: BaseBeanData<PhonePwdLoginBean>)
this@MainActivity.toast(t.msg)
if (TextUtils.equals(ApiSuccessCode, t.code))
//登录成功,接口返回200成功值
else
//登录失败
LogUtil.e("$t")
//登录成功,存起来必要数据,给header添加
SpUtil.put("UserID", "1234567890")
SpUtil.put("UserName", "abcdefg")
override fun onError(throwable: Throwable)
super.onError(throwable)
this@MainActivity.toast("登录失败")
)
4、还是登录接口,模拟非表单提交
/**
* 手机号,密码登陆。非表单提交
*/
@POST("abc/abc")
fun toMobilePwdLogin2(@Body body: RequestBody): Observable<BaseBeanData<PhonePwdLoginBean>>
//----------------------------------
/**
* 手机号、密码登陆。非表单提交
*
*/
fun toMobilePwdLogin2(
phone:String,
pwd:String,
observer: ApiBaseObserver<BaseBeanData<PhonePwdLoginBean>>
)
val jsonObject = JSONObject().apply
put("mobile", phone)
put("pwd", pwd)
//为了看参数排序,额外加的
put("higk", "higk")
put("nop", "nop")
val toRequestBody = jsonObject.toString()
.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
apiZmService.toMobilePwdLogin2(toRequestBody)
.compose(RxBiz.transformMain())
.subscribe(observer)
//-------------------------------------------
ApiServiceImpl.toMobilePwdLogin2(
"123123",
"a1234567",
object : ApiBaseObserver<BaseBeanData<PhonePwdLoginBean>>()
override fun onNext(t: BaseBeanData<PhonePwdLoginBean>)
this@MainActivity.toast(t.msg)
if (TextUtils.equals(ApiSuccessCode, t.code))
//登录成功,接口返回200成功值
else
//登录失败
LogUtil.e("$t")
//登录成功,存起来必要数据,给header添加
SpUtil.put("UserID", "1234567890")
SpUtil.put("UserName", "abcdefg")
override fun onError(throwable: Throwable)
super.onError(throwable)
this@MainActivity.toast("登录失败")
)
以上是关于网络框架封装(retrofit2+rxjava2+okhttp3)的主要内容,如果未能解决你的问题,请参考以下文章
RxJava2+Retrofit2+RxLifecycle3+OkHttp3网络请求封装(动态演示)
一款基于RxJava2+Retrofit2实现简单易用的网络请求框架
基于RxJava2+Retrofit2的简单易用网络请求框架
Android RxJava2+Retrofit2单文件下载监听进度封装