前言
看了公司封裝的網(wǎng)絡請求,就是對OkHttp和Gson的封裝。看了一下代碼,里面好多都是鴻洋大佬寫的 okhttp-utils 。當然,光看不寫還是很難領悟,于是想用Kotlin來試著寫寫看。
在這之前,先看我之前封裝的簡單的寫法(只貼出異步Get請求):
public class OkHttpUtil {
private static OkHttpUtil sOkHttpUtil = null;
private OkHttpClient mHttpClient;
private Request mRequest;
private OkHttpUtil(){
}
public static OkHttpUtil getInstance() {
if (sOkHttpUtil == null) {
synchronized (OkHttpUtil.class) {
if (sOkHttpUtil == null) {
sOkHttpUtil = new OkHttpUtil();
}
}
}
return sOkHttpUtil;
}
public void startGet(String url, final OnNetResultListener listener) {
mHttpClient = new OkHttpClient();
mRequest = new Request.Builder().url(url).build();
mHttpClient.newCall(mRequest).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
listener.onFailureListener(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
listener.onSuccessListener(response.body().string());
}
});
}
}
其實就是用接口回調結果,但這樣有兩個問題:
- 每次都要拿到回調結果后手動反序列化
- 回調在非UI線程,也就是還的寫Handle處理
那能不能一步到位呢?當然可以,最終寫法如下:
OkHttpClientManager.getAsync(url,object :ResultCallback<ResultBean>(){
override fun onError(request: Request, exception: Exception) {
}
override fun onResponse(response: ResultBean) {
mTextView.text = response.name
}
})
其實實現(xiàn)也很簡單,關鍵是怎么把泛型參數(shù)轉化為具體的JavaBean實例,完整源碼如下,只貼出了GET請求:
package top.omooo.mylibrary.network
import android.os.Handler
import android.os.Looper
import com.google.gson.Gson
import com.google.gson.internal.`$Gson$Types`
import okhttp3.*
import java.io.IOException
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
/**
* Created by ssc on 2018/8/6.
*/
object OkHttpClientManager {
private val mOkHttpClient by lazy {
OkHttpClient()
}
private val mHandler by lazy {
Handler(Looper.getMainLooper())
}
private val mGson by lazy {
Gson()
}
//同步Get請求
private fun getSync(url: String): Response {
val request = Request.Builder()
.url(url)
.build()
val call = mOkHttpClient.newCall(request)
return call.execute()
}
fun getSyncString(url: String): String {
return getSync(url).body()!!.string()
}
//異步Get請求
fun getAsync(url: String, callback: ResultCallback<*>) {
val request = Request.Builder()
.url(url)
.build()
deliverResult(callback, request)
}
private fun deliverResult(callback: ResultCallback<*>, request: Request) {
mOkHttpClient.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call?, e: IOException) {
sendFailedStringCallback(request, e, callback)
}
override fun onResponse(call: Call?, response: Response?) {
val string = response?.body()!!.string()
val mObject = mGson.fromJson<Any>(string, callback.mType)
sendSuccessResultCallback(mObject, callback as ResultCallback<Any>)
}
})
}
fun sendFailedStringCallback(request: Request, exception: Exception, callback: ResultCallback<*>) {
mHandler.post {
callback.onError(request, exception)
}
}
fun sendSuccessResultCallback(mObject: Any, callback: ResultCallback<Any>) {
mHandler.post {
callback.onResponse(mObject)
}
}
}
abstract class ResultCallback<T> {
val mType: Type by lazy {
getSuperclassTypeParameter(javaClass)
}
companion object {
fun getSuperclassTypeParameter(subclass: Class<*>): Type {
val superclass = subclass.genericSuperclass
if (superclass is Class<*>) {
throw RuntimeException("Miss type parameter.")
}
val parameterizedType = superclass as ParameterizedType
return `$Gson$Types`.canonicalize(parameterizedType.actualTypeArguments[0])
}
}
abstract fun onError(request: Request, exception: Exception)
abstract fun onResponse(response: T)
}
最后
可以參考鴻洋大佬的 Android OkHttp完全解析 是時候來了解OkHttp了
事實上,博客中的代碼相對okhttp-utils 還是很簡單的。