从0开始封装一套项目的网络请求框架
前言
用到的知识
Kotlin、Retrofit,RxJava,OkHttp
步骤介绍
1.api介绍
在这里使用鸿洋大神的开放api,链接点这里。只使用登录api即可,其他的api都是一样的方式。
url:https://www.wanandroid.com/user/login
方法:POST
参数:username,password
这里推荐一款很好用的接口测试工具Apipost,我这边测试一下登录的接口
它返回的response由三部分组成,分别是data,errorCode,errorMsg。我把结果粘贴过来
{
"data": {
"admin": false,
"chapterTops": [],
"coinCount": 10,
"collectIds": [],
"email": "",
"icon": "",
"id": 130077,
"nickname": "LJH111",
"password": "",
"publicName": "LJH111",
"token": "",
"type": 0,
"username": "LJH111"
},
"errorCode": 0,
"errorMsg": ""
}
2.创建项目
创建一个kotlin项目,完成必要的准备
①依赖导入
在app模块的gradle文件中导入retrofit和rxjava的依赖
//导入retrofit
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'//ConverterFactory的Gson依赖包
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'//ConverterFactory的String依赖包
implementation("com.squareup.okhttp3:okhttp:4.9.1")
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
//导入rxjava
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile "io.reactivex.rxjava2:rxjava:2.0.8"
②开启网络权限
(1)首先新建一个xml文件,如图
内容是
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
(2)然后找到Menifest文件
在application标签中设置这样的属性
(3)然后,在menifest中打开网络权限
内容为
<!--网络权限-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
3.新建response模板类
所有的response都有一个共性,即由三部分组成,分别是data,errorCode,errorMsg。这里只有data的类型不确定,但是可以用泛型表示。
所以可以用一个通用的模板类来接收所有的Response
/**
* Created by didiwei on 2022/4/20
* desc: 所有请求的模板类
*/
data class ResponseModel<T>(val data: T,
val errorCode: String?,
val errorMsg: String?)
data用泛型表示即可
4.新建登录成功时,返回的data模板类
登录成功时,返回的json如下
{
"data": {
"admin": false,
"chapterTops": [],
"coinCount": 10,
"collectIds": [],
"email": "",
"icon": "",
"id": 130077,
"nickname": "LJH111",
"password": "",
"publicName": "LJH111",
"token": "",
"type": 0,
"username": "LJH111"
},
"errorCode": 0,
"errorMsg": ""
}
其中因为data是不同的api,可能会不一样,所以最好用一个类来区分不同的data。这里登录成功时,返回的data我这样表示
/**
* Created by didiwei on 2022/4/20
* desc: 登录成功时,返回的response中的data的模板类
*/
data class LoginSuccessResData(val admin: Boolean,
val chapterTops: List<*>,
val coinCount: Int,
val collectIds: List<*>,
val email: String?,
val icon: String?,
val id: String?,
val nickname: String?,
val password: String?,
val publicName: String?,
val token: String?,
val type: Int,
val username: String?)
5.自定义RxJava操作符
正常的逻辑应该是这样的,请求成功时,把data丢给UI,请求失败时,把errorMsg丢给UI。所以我们可以自定义RxJava操作符,当数据返回时,对Response完成这样的功能。
/**
* Created by didiwei on 2022/4/20
* desc: RxJava的自定义操作符,用于剥离data和errorMsg
*/
abstract class RxJavaInterceptor<T> : Observer<ResponseModel<T>> {
abstract fun success(data: T?)
abstract fun failure(errorMsg: String?)
override fun onSubscribe(d: Disposable?) {
//这里可以弄个加载dialog的start,别忘了在请求结束(不管成功还是失败)的时候让这个dialog消失
}
override fun onNext(t: ResponseModel<T>?) {
if(t?.data != null){
//请求成功了
success(t?.data)
}else{
//失败
failure(t?.errorMsg)
}
}
override fun onError(e: Throwable?) {
failure(e?.message)
}
override fun onComplete() {
//可以加个dialog的消失
}
}
有个注意点,首先RxJavaInterceptor
类为抽象类,里面的success
和failure
为抽象方法,当调用的时候实现。其次是这里依然是泛型类,适用于各个model
6.写请求的接口
/**
* Created by didiwei on 2022/4/20
* desc: 关于用户登录 注册的api
*/
interface UserService {
/**
* desc 登录的接口
*
* url:https://www.wanandroid.com/user/login
* 方法:POST
* 参数:username,password
*/
@POST("/user/login")
@FormUrlEncoded
fun loginAction(@Field("username")username: String?,
@Field("password")password: String?)
:Observable<ResponseModel<LoginSuccessResData>>
}
注意它的返回值是Observable
类型,作为被观察者,流向观察者(RxJava的知识)
7.创建实例化service的类
/**
* Created by didiwei on 2022/4/20
* desc: 此类是单例类,用于创建Service的实例
*/
class ApiClient {
private object Holder{
val instance = ApiClient()
}
companion object{
val INSTANCE = Holder.instance
}
fun <T> createRetrofit(retrofitInterface: Class<T>) : T{
//创建okhttp
val mOkHttpClient = OkHttpClient().newBuilder()
.readTimeout(10000, TimeUnit.SECONDS)//读取超时时间
.connectTimeout(10000, TimeUnit.SECONDS)//连接超时时间
.writeTimeout(10000, TimeUnit.SECONDS)//写出超时时间
.build()
//创建retrofit
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl("https://www.wanandroid.com")
.client(mOkHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
//返回
return retrofit.create(retrofitInterface)
}
}
8.这样当我们使用的时候,就可以这样用
比如添加一个登录按钮,然后注册其点击事件
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val userLoginBtn: Button = findViewById<Button>(R.id.userLoginBtn)
userLoginBtn.setOnClickListener(onClickListener)
}
private val onClickListener = View.OnClickListener {
when(it.id){
R.id.userLoginBtn ->{
val userName = "LJH111"
val userPwd = "123456"
ApiClient.INSTANCE.createRetrofit(UserService::class.java)
.loginAction(userName,userPwd)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : RxJavaInterceptor<LoginSuccessResData>(){
override fun success(data: LoginSuccessResData?) {
Log.v("ljh","请求成功,返回的data为:${data}")
}
override fun failure(errorMsg: String?) {
Log.v("ljh","请求失败,错误信息为:${errorMsg}")
}
})
}
}
}
}
效果
如果改成错误的用户名或密码,效果是这样的
至此,我们就完成了网络请求规则的封装
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgcccke
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13