记OKHTTP的二次封装

1,625 阅读1分钟

1. 环境

  • language: kotlin
  • okhttp.version: 4.9.1

2. 思路

目标: 针对异步请求封装

1. 最低层:封装请求callback:打印请求地址、请求失败提示

abstract class BaseCallback(private val context: Context, private val url: String?) : Callback {
    override fun onResponse(call: Call, response: Response) {
        if (!response.isSuccessful) throw IOException("Unexpected code $response")
        Log.d(this.javaClass.name, "请求成功: $url")
    }

    override fun onFailure(call: Call, e: IOException) {
        Log.d(this.javaClass.name, "请求失败: $url")
        e.printStackTrace()
        Handler(Looper.getMainLooper()).run {
            post {
                Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

2. 第二层:封装OkHttpClient、异步请求的调用方式。把请求后的需要具体执行函数抛给外部

object BaseClient {
    private val INSTANCE = OkHttpClient.Builder()
        .connectTimeout(3, TimeUnit.SECONDS)
        .retryOnConnectionFailure(true)
        .build()

    fun baseRequestAsync(
        context: Context,
        request: Request,
        onResponse: ((response: Response) -> Unit)?,
        onFailure: ((exception: Exception) -> Unit)?
    ) {
        INSTANCE.newCall(request).enqueue(
            object : BaseCallback(context, request.url.encodedPath) {
                override fun onResponse(call: Call, response: Response) {
                    super.onResponse(call, response)
                    onResponse?.invoke(response)
                }

                override fun onFailure(call: Call, e: IOException) {
                    super.onFailure(call, e)
                    onFailure?.invoke(e)
                }
            }
        )
    }
}

3. 最外层:构造请求,例:通过使用键值对的形式的请求参数来构造get、form请求

fun get(
        context: Context,
        url: String,
        data: Map<String, *>?,
        onResponse: ((response: Response) -> Unit)?,
        onFailure: ((exception: Exception) -> Unit)?
    ) {
        val build = url.toHttpUrlOrNull()?.newBuilder().apply {
            data?.forEach { (t, u) -> this!!.addEncodedQueryParameter(t, u.toString()) }
        }!!.build()
        val request = Request.Builder()
            .url(build)
            .get()
            .build()
        BaseClient.baseRequestAsync(context, request, onResponse, onFailure)
    }

3. 实战

例:app获取版本更新(h5压缩包)

private fun updateVersion() {
        HttpUtil.get(
            this,
            "${HttpUtil.myFileUrl}/filesystem/download/android/web/version",
            null,
            {
                val serverVersion =
                    GsonUtil.instance.fromJson(it.body?.string(), Version::class.java)
                val currentVersion = this.getVersion()
                if (null == currentVersion || serverVersion.updateTime!! > currentVersion.updateTime) {
                    FileUtil.mkdir("${filesDir.path}/web")
                    HttpUtil.get(
                        this,
                        "${HttpUtil.myFileUrl}/filesystem/download/android/web",
                        mapOf<String, Any?>("objectId" to serverVersion.objectId),
                        {
                            val file = File("${filesDir.path}/web/dist.zip")
                            file.outputStream().run {
                                write(it.body?.bytes())
                            }
                            /*解压H5文件*/
                            FileUtil.upZipFile(
                                "${filesDir.path}/web/dist.zip",
                                "${filesDir.path}/web"
                            )
                            this.saveVersion(serverVersion)

                            runOnUiThread {
                                this.startActivity(Intent(this, MainActivity::class.java))
                                finish()
                            }
                        },
                        null
                    )
                } else {
                    runOnUiThread {
                        this.startActivity(Intent(this, MainActivity::class.java))
                        finish()
                    }
                }
            },
            null
        )
    }

不相关的类这里没写。 详细信息可去代码地址:网络请求封装包app获取版本更新

后续更新:做了些改动放到了maven仓库供拉取。工具之二次封装OKHTTP,可直接引入项目