1. 程式人生 > >Kotlin okhttp 簡單封裝

Kotlin okhttp 簡單封裝

第一次寫部落格,感覺還是有點的小激動。
主要對自己開始學習Kotlin的過程做個記錄,畢竟好記性不如爛筆頭。雖然我一直都沒有做到,這可能是個開始。
依賴的新增:

 implementation 'com.squareup.okhttp3:okhttp:3.1.2'
 implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.60'
 // 這裡有一個大坑啊。fastjson版本不是1.2.36和1.1.61是不支援Kotlin的。希望官網是早日更新
 implementation 'com.alibaba:fastjson:1.2.36'
implementation 'com.alibaba:fastjson:1.1.61.android'

首先是對okhttp的封裝

import okhttp3.Interceptor
import okhttp3.OkHttpClient
import java.util.concurrent.TimeUnit

class HttpManager private constructor() {

    var httpClient: OkHttpClient? = null
    val timeUnit: TimeUnit = TimeUnit.SECONDS
    val connectTimeOut: Long
= 10 val readTimeOut: Long = 10 val writeTimeOut: Long = 10 var interceptors: ArrayList<Interceptor> = ArrayList() var networkInterceptors: ArrayList<Interceptor> = ArrayList() companion object { fun instace() = Holder.INSTACE } private object Holder { val INSTACE
= HttpManager() init { INSTACE.initHttpClient() } } fun initHttpClient(): OkHttpClient? { var builder = OkHttpClient.Builder() .connectTimeout(connectTimeOut, timeUnit) .readTimeout(readTimeOut, timeUnit) .writeTimeout(writeTimeOut, timeUnit) builder = initInterceptor(builder, interceptors) builder = initNetworkInterceptor(builder, networkInterceptors) httpClient = builder.build() return httpClient } fun addInterceptor(interceptors: ArrayList<Interceptor>) { this.interceptors = interceptors } fun addNetworkInterceptor(interceptors: ArrayList<Interceptor>) { this.networkInterceptors = interceptors } fun initInterceptor(builder: OkHttpClient.Builder?, interceptors: ArrayList<Interceptor>?): OkHttpClient.Builder? { interceptors?.forEach { i: Interceptor? -> if (i != null) builder?.addInterceptor(i) } return builder } fun initNetworkInterceptor(builder: OkHttpClient.Builder?, networkInterceptors: ArrayList<Interceptor>?): OkHttpClient.Builder? { networkInterceptors?.forEach { i: Interceptor? -> if (i != null) builder?.addNetworkInterceptor(i) } return builder } }

okhttp封裝好了後就可以對請求rquest進行封裝了

import com.base.http.callback.AbstractCallback
import okhttp3.*
import java.io.IOException

class RequestManager {

    var okHttpClient: OkHttpClient? = null
    var builder: Request.Builder? = null

    init {
        builder = Request.Builder()
    }

    constructor() {
        okHttpClient = HttpManager.instace().httpClient
    }

    constructor(okHttpClient: OkHttpClient?) {
        if (okHttpClient == null)
            RequestManager()
        else
            this.okHttpClient = okHttpClient
    }

    fun doGet(url: String, headers: HashMap<String, String>? = null, params: HashMap<String, String>? = null): RequestManager {
        if (url.isBlank())
            return this
        if (headers != null)
            addHeaders(headers)
        builder!!.url(if (params != null) setGetParams(url, params) else url).get()
        return this
    }

    fun doPost(url: String, headers: HashMap<String, String>? = null, params: HashMap<String, String>? = null): RequestManager {
        if (url.isBlank())
            return this
        if (headers != null)
            addHeaders(headers)
        builder!!.url(url)
        builder!!.post(setPostParams(params))
        return this
    }

    fun addHeaders(headers: HashMap<String, String>) {
        headers.entries.forEach { entry ->
            headers.keys
            builder?.addHeader(entry.key, entry.value)
        }
    }

    fun setGetParams(url: String, params: HashMap<String, String>): String {
        var sb = StringBuilder(url)
        if (params.isNotEmpty()) sb.append("?") else sb
        params.forEach { entry ->
            params.keys
            sb.append(entry.key + "=" + entry.value + "&")
        }
        return if (sb.toString().endsWith("&")) sb.subSequence(0, sb.lastIndex).toString() else sb.toString()
    }

    fun setPostParams(params: HashMap<String, String>?): RequestBody? {
        var builder = FormBody.Builder()
        params?.forEach { entry ->
            params.keys
            builder.add(entry.key, entry.value)
        }
        return builder.build()
    }

    fun execute(abstractCallback: AbstractCallback) {
        okHttpClient!!.newCall(builder!!.build())?.enqueue(object : Callback {
            override fun onResponse(call: Call?, response: Response) {
                abstractCallback.succeed(call, response)
            }

            override fun onFailure(call: Call?, e: IOException?) {
                abstractCallback.failed(call, e)
            }
        })
    }
}

請求封裝好了後就可以對我們的回撥進行統一處理了。首先是定義了一個抽象的回撥類當然介面也是沒有問題的

import okhttp3.Call
import okhttp3.Response
import java.lang.Exception

abstract class AbstractCallback{
    abstract fun succeed(call: Call?, response: Response)

    abstract fun failed(call: Call?, e: Exception?)
}

定義好基類的抽象回撥後我們可繼承它來對我們的資料進行一些處理了。如返回string資料

import android.util.Log
import okhttp3.Call
import okhttp3.Response
import java.io.IOException

abstract class BasicCallback : AbstractCallback() {
    val TAG = BasicCallback::class.java.simpleName
    abstract fun succeed(call: Call?, result: String)

    override fun succeed(call: Call?, response: Response) {
        try {
            if (call!!.isCanceled()) {
                failed(call, IOException("Canceled!"))
                return
            }
            Log.e(TAG, "request:" + call.request().toString())
            Log.e(TAG, "response:" + response.toString())
            if (response.code() !in 200..299) { // 返回Code不在200-299請求失敗
                failed(call, IOException("request failed , reponse's code is : " + response.code()))
                return
            }
            val str = response.body()!!.string()
            Log.e(TAG, str)
            succeed(call, str)
        } catch (e: Exception) {
            Log.e(TAG, e.toString() + "")
            failed(call, e)
        } finally {
            if (response.body() != null)
                response.body()!!.close()
        }
    }

}

由於伺服器一般返回JSON資料所以我封裝了個直接返回物件的回撥,我在這使用的fastjson。
fastjson解析物件方法

class JsonParser {

    companion object {
        fun <T> parserToBean(jsonStr: String, clz: Class<T>) : T {
            return JSON.parseObject(jsonStr,clz)
        }
}

返回物件回撥類定義

import android.util.Log
import com.base.http.parser.JsonParser
import okhttp3.Call
import okhttp3.Response
import java.io.IOException

abstract class JsonCallback<T>(var clz: Class<T>) : AbstractCallback() {

    val TAG = JsonCallback::class.java.simpleName

    abstract fun succeed(call: Call?, data: T)

    override fun succeed(call: Call?, response: Response) {
        try {
            if (call!!.isCanceled()) {
                failed(call, IOException("Canceled!"))
                return
            }
            Log.e(TAG,"request:" + call.request().toString())
            Log.e(TAG,"response:" + response.toString())
            if (response.code() !in 200..299) {
                failed(call, IOException("request failed , reponse's code is : " + response.code()))
                return
            }
            val str = response.body()!!.string()
            Log.e(TAG,str)
            succeed(call, JsonParser.parserToBean(str, clz))
        } catch (e: Exception) {
            Log.e(TAG,e.toString() + "")
            failed(call, e)
        } finally {
            if (response.body() != null)
                response.body()!!.close()
        }
    }

}

寫到這簡單封裝就寫完了,只有post和get請求。檔案的上傳和下載還未新增。
最後就是使用了

fun sendRequest() {
    val params = HashMap<String, String>()
    params["key"] = "value"
    requestManager.doPost(url,header,params).execute(object:JsonCallback<Bean>(Bean::class.java) {
                override fun succeed(call: Call?, data: Bean) {
                    // data就是返回物件了

                }

                override fun failed(call: Call?, e: Exception?) {
                }

            })
        }

寫完收工。檔案的上傳和下載呢?加油