网络框架封装(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单文件下载监听进度封装

基于RxJava2+Retrofit2精心打造的Android基础框架XSnow

基于RxJava2+Retrofit2精心打造的Android基础框架XSnow