Kotlin OKHTTP3和拦截器的使用

注意:在android6.0以后网络请求还需如下配置:

android:usesCleartextTraffic="true"

复制代码
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:usesCleartextTraffic="true"
    android:theme="@style/AppTheme">
  ***
</application>

一、引入okhttp3包

复制代码
 //okhttp3
 implementation("com.squareup.okhttp3:okhttp:4.9.0")
 implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")

二、创建单例对象

复制代码
package com.example.buju.http

import android.content.Context
import android.os.Environment
import android.util.Log
import android.widget.Toast
import okhttp3.Call
import okhttp3.Callback
import okhttp3.FormBody
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
import org.json.JSONObject
import java.io.File
import java.io.IOException
import java.util.concurrent.TimeUnit
/**
 * 单例对象
 *  -http请求工具类
 * */
object HiOkhttp {

    /*  private val client:OkHttpClient
        // 最早调用模块
        init {
             val httpLoggingInterceptor = HttpLoggingInterceptor()// okhttp3自带拦截器
             httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
             client = OkHttpClient.Builder()// builder构造者设计模式
                 .connectTimeout(10,TimeUnit.SECONDS)//连接超时时间
                 .readTimeout(10,TimeUnit.SECONDS)// 读取超时
                 .writeTimeout(10,TimeUnit.SECONDS)// 写超时
                 .addInterceptor(httpLoggingInterceptor)// 自带拦截器
                 .build()

         }*/

    val client = OkHttpClient.Builder()// builder构造者设计模式
        .connectTimeout(10,TimeUnit.SECONDS)//连接超时时间
        .readTimeout(10,TimeUnit.SECONDS)// 读取超时
        .writeTimeout(10,TimeUnit.SECONDS)// 写超时
        .addInterceptor(LoggingInterceptor())// 自定义拦截器
        .build()

    // android 分为主线程和子线程
    // 主线程就是APP一启动后,咱们android framework层会启动一个线程,主线程(UI线程)
    // 子线程 - new Thread().start()


    /**
     * get请求
     *  -同步请求不要放在主线程中执行,容易阻塞线程
     * */
    fun syncGet(url:String){
        // 构造请求体
        val request:Request = Request.Builder()
            .url(url)
            .build()

        // 构造请求对象
        val call:Call = client.newCall(request)

      Thread(Runnable {// 构建子线程
          // execute() - 发起同步请求(同步执行)
          val  response:Response = call.execute()
          val body: String? = response.body?.string()
          Log.e("OKHTTP","get response:${body}")
      }).start()
    }

    /**
     * get请求
     *  -异步请求
     * */
    fun asyncGet(url:String){
        // 构造请求体
        val request:Request = Request.Builder()
            .url(url)
            .build()

        // 构造请求对象
        val call:Call = client.newCall(request)

        // enqueue() - 发起异步请求(异步执行)
       call.enqueue(object :Callback{
            override fun onFailure(call: Call, e: IOException) {
                Log.e("OKHTTP","get onFailure:${e.message}")
            }

            override fun onResponse(call: Call, response: Response) {
                val body:String? = response.body?.string()
                Log.e("OKHTTP","get response:${body}")
            }

        })

    }

    /**
     * post请求
     *  -同步表单请求,不要放在主线程中执行,容易阻塞线程
     * */
    fun syncPost(url:String){
        val body = FormBody.Builder()
            .add("userId","123")
            .add("userName","zs")
            .build()

        val request:Request = Request.Builder()
            .url(url)
            .post(body)
            .build()

        val call:Call = client.newCall(request)

        Thread(Runnable {
            val response:Response = call.execute()
            val resultBody = response.body?.string()
            Log.e("OKHTTP","post response:${resultBody}")
        }).start()

    }

    /**
     * post请求
     *  -异步表单请求
     * */
    fun asyncPost(url:String){
        val body = FormBody.Builder()
            .add("userId","123")
            .add("userName","zs")
            .build()

        val request:Request = Request.Builder()
            .url(url)
            .post(body)
            .build()

        val call:Call = client.newCall(request)

        call.enqueue(object :Callback{
            override fun onFailure(call: Call, e: IOException) {
                Log.e("OKHTTP","post onFailure:${e.message}")
            }

            override fun onResponse(call: Call, response: Response) {
                val resultBody = response.body?.string()
                Log.e("OKHTTP","post response:${resultBody}")
            }

        })


    }


    /**
     * post请求
     *  -异步多表单文件上传请求
     *  -url必须支持文件上传的接口
     *  -android6.0以后,读取外部存储卡的文件都是需要动态申请权限
     * */
    fun asyncPostMultipart(url:String,context:Context){
        val file = File(Environment.getExternalStorageDirectory(),"demo.png")
        if (!file.exists()){
            Toast.makeText(context,"文件不存在",Toast.LENGTH_LONG).show()
            return
        }

        val body = MultipartBody.Builder()
            .addFormDataPart("key1","value1")
            .addFormDataPart("key2","value2")
            .addFormDataPart("file",
                "file.png",
                RequestBody.create("application/octet-stream".toMediaType(), file))
            .build()

        val request:Request = Request.Builder()
            .url(url)
            .post(body)
            .build()

        val call:Call = client.newCall(request)

        call.enqueue(object :Callback{
            override fun onFailure(call: Call, e: IOException) {
                Log.e("OKHTTP","post onFailure:${e.message}")
            }

            override fun onResponse(call: Call, response: Response) {
                val resultBody = response.body?.string()
                Log.e("OKHTTP","post response:${resultBody}")
            }

        })


    }

    /**
     * post请求
     *  -异步字符串请求
     * */
    fun asyncPostString(url:String){
        // 纯文本
       /* val textPlain = "text/plain;charset=utf-8".toMediaType()

        val textObj = "username:username;password:1234"

        val body = RequestBody.create(textPlain,textObj)*/
        // json对象
        val applicationJson = "application/json;charset=utf-8".toMediaType();

        val jsonObj = JSONObject()
        jsonObj.put("key1","val1")
        jsonObj.put("key2","val2")

        val body = RequestBody.create(applicationJson,jsonObj.toString())

        val request = Request.Builder()
            .url(url)
            .post(body)
            .build()

        val call:Call = client.newCall(request)

        call.enqueue(object :Callback{
            override fun onFailure(call: Call, e: IOException) {
                Log.e("OKHTTP","post onFailure:${e.message}")
            }

            override fun onResponse(call: Call, response: Response) {
                val resultBody = response.body?.string()
                Log.e("OKHTTP","post response:${resultBody}")
            }

        })



    }


}

三、自定义okhttp3拦截器

复制代码
package com.example.buju.http

import android.util.Log
import okhttp3.Interceptor
import okhttp3.Response
import okhttp3.ResponseBody
import okio.Buffer

/**
 * OKHttp3 拦截器
 * */
class LoggingInterceptor:Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val time_start = System.nanoTime()// 开始时间戳
        val request = chain.request()// 请求
        val response = chain.proceed(request)// 响应

        /**
         * 获取请求信息
         * */
        val buffer = Buffer()// okio.Buffer
        request.body?.writeTo(buffer)
        val requestBodyStr = buffer.readUtf8()
        // request.url - 请求接口;requestBodyStr - 请求携带的参数
        Log.e("OKHTTP",String.format("Sending request %s with params %s",request.url,requestBodyStr))

       /**
        * 获取响应信息
        * */
        val bussinessData:String = response.body?.string()?:"response body null"
        val mediaType = response.body?.contentType()
        val newBody = ResponseBody.create(mediaType,bussinessData)
        val newResponse = response.newBuilder().body(newBody).build()

        val time_end = System.nanoTime()//结束始时间戳
        //  request.url - 请求接口;(time_end - time_start) -执行时间;bussinessData - 响应数据
        Log.e("OKHTTP",String.format("Received response for %s in %.1fms >>> %s",request.url,(time_end - time_start),bussinessData))

        return newResponse







    }

}
相关推荐
AH_HH13 小时前
SmartCabinet:基于 Android 的智能储物柜管理系统技术解析
android·kotlin·存储柜
西部风情13 小时前
聊聊并发、在线、TPS
android·java·数据库
爬虫程序猿14 小时前
用 Python 给京东商品详情做“全身 CT”——可量产、可扩展的爬虫实战
开发语言·爬虫·python
徐同保15 小时前
tailwindcss暗色主题切换
开发语言·前端·javascript
蓝纹绿茶16 小时前
bash:**:pip:***python: 错误的解释器: 没有那个文件或目录
开发语言·python·pip
云知谷16 小时前
【经典书籍】C++ Primer 第15章类虚函数与多态 “友元、异常和其他高级特性” 精华讲解
c语言·开发语言·c++·软件工程·团队开发
START_GAME16 小时前
深度学习Diffusers:用 DiffusionPipeline 实现图像生成
开发语言·python·深度学习
不爱编程的小九九17 小时前
小九源码-springboot088-宾馆客房管理系统
java·开发语言·spring boot
Evand J17 小时前
【MATLAB例程】到达角度定位(AOA),平面环境多锚点定位(自适应基站数量),动态轨迹使用EKF滤波优化。附代码下载链接
开发语言·matlab·平面·滤波·aoa·到达角度
细节控菜鸡18 小时前
【2025最新】ArcGIS for JS 实现随着时间变化而变化的热力图
开发语言·javascript·arcgis