1. Environmental

  • language: kotlin
  • Okhttp. Version: 4.9.1

2. The train of thought

Target: Encapsulation for asynchronous requests

1. The lowest layer: encapsulates the request callback: Prints the request address and request failure prompt

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, "Request successful:$url")}override fun onFailure(call: Call, e: IOException) {
        Log.d(this.javaClass.name, "Request failed:$url")
        e.printStackTrace()
        Handler(Looper.getMainLooper()).run {
            post {
                Toast.makeText(context, "Network error", Toast.LENGTH_SHORT).show()
            }
        }
    }
}
Copy the code

2. Layer 2: Encapsulates the invocation mode of OkHttpClient and asynchronous requests. After the request to the specific execution of the function thrown to the outside

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) } } ) } }Copy the code

Outermost: construct requests. For example, construct GET and form requests by using request parameters in the form of key-value pairs

fun get(
        context: Context,
        url: String.data: Map<String, * >? , onResponse: ((response: Response) - >Unit)? , onFailure: ((exception: Exception) - >Unit)? {
        valbuild = 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)
    }
Copy the code

3. The actual combat

Example: App get version update (H5 compressed package)

private fun updateVersion(a) {
        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())
                            }
                            /* Unzip the H5 file */
                            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)}Copy the code

Irrelevant classes are not written here. Details can go to the code address: network request encapsulation package, APP to obtain version updates