前言
看了公司封装的网络请求,就是对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
}
})
其实实现也很简单,关键是怎么把泛型参数转化为具体的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 还是很简单的。