Android - kotlin简易封装网络请求OkHttp

一、okhttp库

dependencies {
 ...
 implementation 'com.squareup.okhttp3:okhttp:4.1.0'
}

首先需要创建一个OkHttpClient的实例

val client = OkHttpClient()

接下来如果想要发起一条HTTP请求,就需要创建一个Request对象:

val request = Request.Builder().build() 

在最终的 build()方法之前连缀很多其他方法来丰富这个Request对象。比如可以通过url()方法来设 置目标的网络地址

val request = Request.Builder()
 .url("https://www.baidu.com")
 .build()

 之后调用OkHttpClient的newCall()方法来创建一个Call对象,并调用它的execute()方法 来发送请求并获取服务器返回的数据

val response = client.newCall(request).execute()

Response对象就是服务器返回的数据了,我们可以使用如下写法来得到返回的具体内容

val responseData = response.body?.string() 

POST请求,会比GET请求稍微复杂一点,我们需要先构建一个Request Body 对象来存放待提交的参数,

val requestBody = FormBody.Builder()
 .add("username", "admin")
 .add("password", "123456")
 .build()

 然后在Request.Builder中调用一下post()方法,并将RequestBody对象传入

val request = Request.Builder()
 .url("https://www.baidu.com")
 .post(requestBody)
 .build()

 接下来的操作就和GET请求一样了,调用execute()方法来发送请求并获取服务器返回的数据 即可。

使用:

class MainActivity : AppCompatActivity() {
 override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 setContentView(R.layout.activity_main)
 sendRequestBtn.setOnClickListener {
 sendRequestWithOkHttp()
 }
 }
 ...
 private fun sendRequestWithOkHttp() {
 thread {
 try {
 val client = OkHttpClient()
 val request = Request.Builder()
 .url("https://www.baidu.com")
 .build()
 val response = client.newCall(request).execute()
 val responseData = response.body?.string()
 if (responseData != null) {
 showResponse(responseData)
 }
 } catch (e: Exception) {
 e.printStackTrace()
 }
 }
 }
}

二、网络请求回调的实现方式

一个应 用程序很可能会在许多地方都使用到网络功能,而发送HTTP请求的代码基本是相同的,如果我 们每次都去编写一遍发送HTTP请求的代码,这显然是非常差劲的做法,可以封装

object HttpUtil {
 ...
 fun sendOkHttpRequest(address: String, callback: okhttp3.Callback) {
 val client = OkHttpClient()
 val request = Request.Builder()
 .url(address)
 .build()
 client.newCall(request).enqueue(callback)
 
}
 }
 // 回调onFinish()方法
 listener.onFinish(response.toString())
 } catch (e: Exception) {
 e.printStackTrace()
 // 回调onError()方法
 listener.onError(e)
 } finally {
 connection?.disconnect()
 }
 }
 }
}

在接口中定义了两个方法:onFinish()方法表示当服务器成功响应我们请求 的时候调用,onError()表示当进行网络操作出现错误的时候调用。这两个方法都带有参数, onFinish()方法中的参数代表服务器返回的数据,而onError()方法中的参数记录着错误的 详细信息。 

interface HttpCallbackListener {
 fun onFinish(response: String)
 fun onError(e: Exception)
}

先给sendHttpRequest()方法添加了一个HttpCallbackListener参数,并在方法 的内部开启了一个子线程,然后在子线程里执行具体的网络操作。注意,子线程中是无法通过 return语句返回数据的,因此这里我们将服务器响应的数据传入了HttpCallbackListener 的onFinish()方法中,如果出现了异常,就将异常原因传入onError()方法中。 现在sendHttpRequest()方法接收两个参数,因此我们在调用它的时候还需要将 HttpCallbackListener的实例传入

HttpUtil.sendHttpRequest(address, object : HttpCallbackListener {
 override fun onFinish(response: String) {
 // 得到服务器返回的具体内容
 }
 override fun onError(e: Exception) {
 // 在这里对异常情况进行处理
 }
})

这样当服务器成功响应的时候,我们就可以在onFinish()方法里对响应数据进行处理了。类 似地,如果出现了异常,就可以在onError()方法里对异常情况进行处理。如此一来,我们就 巧妙地利用回调机制将响应数据成功返回给调用方了。

sendOkHttpRequest()方法中有一个okhttp3.Callback参数,这个是OkHttp 库中自带的回调接口,类似于我们刚才自己编写的HttpCallbackListener。然后在 client.newCall()之后没有像之前那样一直调用execute()方法,而是调用了一个 enqueue()方法,并把okhttp3.Callback参数传入。相信聪明的你已经猜到了,OkHttp在 enqueue()方法的内部已经帮我们开好子线程了,然后会在子线程中执行HTTP请求,并将最 终的请求结果回调到okhttp3.Callback当中。 那么我们在调用sendOkHttpRequest()方法的时候就可以这样写

HttpUtil.sendOkHttpRequest(address, object : Callback {
 override fun onResponse(call: Call, response: Response) {
 // 得到服务器返回的具体内容
 val responseData = response.body?.string()
 }
 override fun onFailure(call: Call, e: IOException) {
 // 在这里对异常情况进行处理
 }
})

需要注意的是,不管是使用HttpURLConnection还是OkHttp,最终的回调接口都还是 在子线程中运行的,因此我们不可以在这里执行任何的UI操作,除非借助runOnUiThread() 方法来进行线程转换

下一篇:Retrofit的用法

你可能感兴趣的:(android,okhttp)