目录
概述
第一步,app/build.gradle里添加okhttp3的依赖,分为Okhttp,和logging-interceptor
// define a BOM and its version
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0"))
// define any required OkHttp artifacts without version
implementation("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okhttp3:logging-interceptor")
第二步,AndroidManifest.xml里添加网络权限
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
第三步,新建网络请求类Hiokhttp
get请求
- 通过OkHttpClient构造client对象
- 通过Request.Builder构建一个request实例(要在子线程里完成)
- 通过client.newCall构建Call实例
- 通过call.execute发起同步请求/通过call.enqueue发起异步请求
- 通过response转String类型接收响应结果
同步请求execute,会阻塞线程,因此需要在子线程完成
object Hiokhttp {
private const val TAG = "Hiokhttp"
private var BASE_URL = "https://jsonplaceholder.typicode.com/users"
//构造Http对象
private var client:OkHttpClient = OkHttpClient().newBuilder()
.connectTimeout(10L,TimeUnit.SECONDS)
.readTimeout(10L,TimeUnit.SECONDS)
.writeTimeout(10L,TimeUnit.SECONDS)
.build()
//发起同步请求
fun getExe(){
Thread {
//构造请求体request
val request = Request.Builder().url("$BASE_URL?id=2").get().build()
//发起call请求
val call: Call = client.newCall(request)
//同步请求
val response = call.execute()
//接收返回响应
val result = response.body?.string()
Log.d(TAG, "result:{$result}")
}.start()
}
}
异步请求enqueue,无需创建子线程发起请求。
无论同步还是异步请求,onFailure、onResponse的回调都是在子线程,我们需要切换到主线程才能操作UI控件。
子线程切换的方式有handle和runOnUiThread()
//发起异步请求
fun getEnq(){
//构造请求体request
val request = Request.Builder().url("$BASE_URL?id=3").get().build()
//发起call请求
val call: Call = client.newCall(request)
//异步请求
call.enqueue(object :Callback{
override fun onFailure(call: Call, e: IOException) {
Log.d(TAG, "onFailure IOException:{$e}")
}
override fun onResponse(call: Call, response: Response) {
//接收返回响应
val result = response.body?.string()
Log.d(TAG, "result:{$result}")
}
})
post请求
post请求与get请求类似,不同在于,post方法接收的是FormBody.Builder()构造的body对象
//post发起同步请求
fun postExe(){
val body: RequestBody = FormBody.Builder().add("id","1").build()
val request = Request.Builder().url(BASE_URL).post(body).build()
Thread(Runnable {
val call = client.newCall(request)
val response = call.execute()
val result = response.body?.string()
Log.d(TAG,"result:{$result}")
}).start()
}
//post发起异步请求
fun postAsync(){
val body = FormBody.Builder().add("id","2").build()
val request = Request.Builder().url(BASE_URL).post(body).build()
client.newCall(request).enqueue(object:Callback{
override fun onFailure(call: Call, e: IOException) {
Log.d(TAG, "onFailure IOException:{$e}")
}
override fun onResponse(call: Call, response: Response) {
//接收返回响应
val result = response.body?.string()
Log.d(TAG, "result:{$result}")
}
})
}
post文件上传
post文件上传,需要MultiPartBody.Builder()构造的body对象
fun postMult() {
val file = File(Environment.getExternalStorageDirectory(), "logo.png")
if (!file.exists()) {
return
}
val body = MultipartBody.Builder()
.addFormDataPart("key", "value")
.addFormDataPart("key1", "value1")
.addFormDataPart(
"file", "logo.png",
file.asRequestBody("application/octet-stream".toMediaType())
)
.build()
val request = Request.Builder().url("支持文件上传的接口").post(body).build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
TODO("Not yet implemented")
}
override fun onResponse(call: Call, response: Response) {
TODO("Not yet implemented")
}
})
}
post上传字符串
post也支持上传字符串,字符串类型可以text,也可以json字符串。
fun postString() {
//上传json字符串
val json = JSONObject()
.put("key", "value")
.put("key1", "value1").toString()
val body = json.toRequestBody("application/json;charset=utf-8".toMediaType())
//上传文本格式的字符串,注意MediaType类型
val text = "text text text"
val body1 = text.toRequestBody("text/plain;charset-utf-8".toMediaType())
val request =
Request.Builder().url("支持上传字符串的接口,这个字符串可以是json,也可以是text文本")
.post(body).build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
TODO("Not yet implemented")
}
override fun onResponse(call: Call, response: Response) {
TODO("Not yet implemented")
}
})
}