鸿洋OkhttpUtils框架总结

来源:互联网 发布:grpc javascript 编辑:程序博客网 时间:2024/05/21 09:06

1、心血来潮

一直想写博客但总不知道该写些什么碰巧最近又比较闲又对 OkHttp 这个框架很热衷想自己尝试封装但是又不知到如何下手于是这篇博文就应运而生了,另外这个框架鸿洋已经停止维护所以不推荐使用了!

虽然说已经停止维护了但还是有学习价值的,比如鸿洋对OkHttp的封装,我很想学学其中的思想,而且鸿洋的框架难度不大正好可以学习学习!

当然了,其实还有一个更深层次的原因,我比较渣!写不出来….. /(ㄒoㄒ)/~~

2、简单使用

鸿洋的OkHttpUtils框架使用起来还是非常简单的,下面我们来看看使用流程!(本篇主要是以析为主,所以更高级的技巧去鸿洋的博客去看看吧)

首先需要创建一个OkHttpClient对象进行配置然后放入OkHttpUtils类进行初始化.配置完后后OkHttpUtils和OkHttpClient就已经完成初始化并可以在全局使用了

至于为什么放入Application中根据OkHttp官方的描述对于请求的各项配置如缓存,cookie应该全局只有一个OkHttpCLient对象方便全局统一调用。

public class MyApplication extends Application{       @Override    public void onCreate()    {        super.onCreate();        OkHttpClient okHttpClient = new OkHttpClient.Builder()//                .addInterceptor(new LoggerInterceptor("TAG"))                  .connectTimeout(10000L, TimeUnit.MILLISECONDS)                  .readTimeout(10000L, TimeUnit.MILLISECONDS)                  //其他配置                 .build();        OkHttpUtils.initClient(okHttpClient);    }}
  • GET 请求
OkHttpUtils    .get()    .url(url)    .addParams("username", "hyman")    .addParams("password", "123")    .build()    .execute(new StringCallback()            {                @Override                public void onError(Request request, Exception e)                {                }                @Override                public void onResponse(String response)                {                }            });
  • POST请求
 OkHttpUtils    .post()    .url(url)    .addParams("username", "hyman")    .addParams("password", "123")    .build()    .execute(callback);
  • POST File
OkHttpUtils    .postFile()    .url(url)    .file(file)    .build()    .execute(new MyStringCallback());
  • POST 表单提交
OkHttpUtils.post()//    .addFile("mFile", "messenger_01.png", file)//    .addFile("mFile", "test1.txt", file2)//    .url(url)    .params(params)//    .headers(headers)//    .build()//    .execute(new MyStringCallback());
  • 下载文件
OkHttpUtils//    .get()//    .url(url)//    .build()//    .execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), "gson-2.2.1.jar")//    {        @Override        public void inProgress(float progress)        {            mProgressBar.setProgress((int) (100 * progress));        }        @Override        public void onError(Request request, Exception e)        {            Log.e(TAG, "onError :" + e.getMessage());        }        @Override        public void onResponse(File file)        {            Log.e(TAG, "onResponse :" + file.getAbsolutePath());        }    });

3、OkhttpUtils框架的总体结构

3.1、项目包结构

  • builder
  • callback
  • cookie
  • https
  • log
  • request
  • utils
  • OkHttputils.class

如上所示,从项目的包结构来看总体框架还是非常清晰的,主体分为三个部分 builder 、callback、request依次点开可以发现其中的类正如包名所描述的一样builder包中放入是关于reqeust构建的类,callback则提供请求结果返回后的回调类等等… 其中OkHttpUtils类相当于一个调度器,通过它获取相应包中的对象来构建一条GET/POST请求

3.2、通过OkHttpUtils.class 分析总体流程

通过上面的 “示例代码” 我们可以发现所有的请求都是通过对 OkHttpUtils.class 这个类的一系列链式调用而生成的那么OkHttpUtils到底做了什么呢? 代码如下所示:

public static final long DEFAULT_MILLISECONDS = 10_000L;    private volatile static OkHttpUtils mInstance;    private OkHttpClient mOkHttpClient;    private Platform mPlatform;    public OkHttpUtils(OkHttpClient okHttpClient)    {        if (okHttpClient == null)        {            mOkHttpClient = new OkHttpClient();        } else        {            mOkHttpClient = okHttpClient;        }        mPlatform = Platform.get();    }    public static OkHttpUtils initClient(OkHttpClient okHttpClient)    {        if (mInstance == null)        {            synchronized (OkHttpUtils.class)            {                if (mInstance == null)                {                    mInstance = new OkHttpUtils(okHttpClient);                }            }        }        return mInstance;    }    public static OkHttpUtils getInstance()    {        return initClient(null);    }    public Executor getDelivery()    {        return mPlatform.defaultCallbackExecutor();    }    public OkHttpClient getOkHttpClient()    {        return mOkHttpClient;    }    public static GetBuilder get()    {        return new GetBuilder();    }    public static PostStringBuilder postString()    {        return new PostStringBuilder();    }    public static PostFileBuilder postFile()    {        return new PostFileBuilder();    }    public static PostFormBuilder post()    {        return new PostFormBuilder();    }    public static OtherRequestBuilder put()    {        return new OtherRequestBuilder(METHOD.PUT);    }    public static HeadBuilder head()    {        return new HeadBuilder();    }    public static OtherRequestBuilder delete()    {        return new OtherRequestBuilder(METHOD.DELETE);    }    public static OtherRequestBuilder patch()    {        return new OtherRequestBuilder(METHOD.PATCH);    }    public void execute(final RequestCall requestCall, Callback callback){    //省略其他代码    }    //省略其他代码

我们来顺着代码来缕缕,首先我们看到了熟悉的 initClient 方法,这个方法返回本类对象而且内部采用 Double Check 机制保证本类的唯一性并且内部对OkHttpCLient进行了初始化,接着往下看我们就可以看到一些在使用中很熟悉的静态方法,比如 get、postString、post等方法。可以发现它们都有一个共同的特性就是返回类似于 XXXBuilder的对象根据名字可以知道应该是对请求进行构建的类, 再往下可以看到一个 execute 方法,这个方法应该是执行请求的方法。

我们可以看到OkHttpUtils这个类好像干了这么几件事,初始化 OkHttpUtils 和 OkHttpClient 对象、根据请求方式调用相应静态方法构建相应的请求,然后通过execute执行请求

大体流程就是这样,下面我们就以点带面从使用的方式上,来看看那些 get、post 静态方法干了些什么

4、以点带面 —— 请求流程分析

4.1、GET请求流程分析

OkHttpUtils    .get()    .url(url)    .addParams("username", "hyman")    .addParams("password", "123")    .build()    .execute(new StringCallback()            {                @Override                public void onError(Request request, Exception e)                {                }                @Override                public void onResponse(String response)                {                }            });

可以看到在发起请求之前经过了一系列链式调用(也就是参数构建)并最终通过execute方法执行相应请求并获取请求的结果。而在这之前首先调用的就是 OkHttpUtils.class 的静态 get 方法,我们跟进去看看做了什么

 public static GetBuilder get()    {        return new GetBuilder();    }

这里面只有一行代码,返回了一个 GetBuilder 对象从字面上我们也可以看出这是对GET请求进行构建,继续跟进

public class  GetBuilder extends OkHttpRequestBuilder<GetBuilder> implements HasParamsable{}

进入后我们发现它继承了 OkHttpRequestBuilder< T extends OkHttpRequestBuilder > 这个类并实现了一个 HasParamsable 接口,我们首先来看 OkHttpRequestBuilder 这个类通过它的泛型声明来看, OkHttpRequestBuilder 对 T 的范围进行了限制,即只能为 OkHttpRequestBuilder 的子类! 看来 GerBuilder 还是隐藏了一些细节,点开 OkHttpRequestBuilder 这个父类看看它做了什么

public abstract class OkHttpRequestBuilder<T extends OkHttpRequestBuilder>{    protected String url;    protected Object tag;    protected Map<String, String> headers;    protected Map<String, String> params;    protected int id;    public T id(int id)    {        this.id = id;        return (T) this;    }    public T url(String url)    {        this.url = url;        return (T) this;    }    public T tag(Object tag)    {        this.tag = tag;        return (T) this;    }    public T headers(Map<String, String> headers)    {        this.headers = headers;        return (T) this;    }    public T addHeader(String key, String val)    {        if (this.headers == null)        {            headers = new LinkedHashMap<>();        }        headers.put(key, val);        return (T) this;    }    public abstract RequestCall build();}

进入之后发现这个父类是一个抽象类,而根据抽象的特性我们就可以知道这里的方法是需要放在子类中使用的,可以看到OkHttpRequestBuilder这个类内部声明了一些请求中必要的参数字段并提供了添加方法,而这些方法的返回值都会被转换为 T 类型(即会被转换子类指定的泛型)到这里就可以明白为什么可以通过不断打 “.” 的方式来添加请求的参数了。 末尾的抽象 build 方法是用来将添加的参数构建成一个 RequestCall 对象具体作用我们在后面在进行分析

至于 HasParamsable 这个接口里面只声明了两个方法如下所示

public interface HasParamsable{    OkHttpRequestBuilder params(Map<String, String> params);    OkHttpRequestBuilder addParams(String key, String val);}

很明显都是用来添加请求参数的,可以通过 GetBuilder 对象进行调用,但是区别就是一个可以直接传入一个Map集合,另一个需要以键值对的方式传入。

继续回到GetBuilder类进行分析代码如下所示

public class  GetBuilder extends OkHttpRequestBuilder<GetBuilder> implements HasParamsable{    @Override    public RequestCall build()    {        if (params != null)        {           //参数不为空则将url和params进行拼接           url = appendParams(url, params);        }        //创建 GetRequest 对象并通过其 build 方法返回一个 RequestCall 对象        return new GetRequest(url, tag, params, headers,id).build();    }    protected String appendParams(String url, Map<String, String> params)    {        if (url == null || params == null || params.isEmpty())        {            return url;        }        Uri.Builder builder = Uri.parse(url).buildUpon();        Set<String> keys = params.keySet();        Iterator<String> iterator = keys.iterator();        while (iterator.hasNext())        {            String key = iterator.next();            builder.appendQueryParameter(key, params.get(key));        }        return builder.build().toString();    }    @Override    public GetBuilder params(Map<String, String> params)    {        this.params = params;        return this;    }    @Override    public GetBuilder addParams(String key, String val)    {        if (this.params == null)        {            params = new LinkedHashMap<>();        }        params.put(key, val);        return this;    }

首先 GetBuilder 重写了父类的 build 方法,这个方法的作用也很简单主要是对params进行了非空判断如果不为空则将 url与params 进行拼接然后返回一个 RequestCall 对象具体代码在这一行

return new GetRequest(url, tag, params, headers,id).build();

可以看到在通过 GetRquest 对象的 build 方法返回 RequestCall 对象之前首先创建了GetRequest对象,并将请求的参数信息传入。我们跟进去看看

public class GetRequest extends OkHttpRequest{    public GetRequest(String url, Object tag, Map<String, String> params, Map<String, String> headers,int id)    {        super(url, tag, params, headers,id);    }    @Override    protected RequestBody buildRequestBody()    {        return null;    }    @Override    protected Request buildRequest(RequestBody requestBody)    {        return builder.get().build();    }}

没什么好说的继承了OkHttpRequest对象,重写了构函数法通过super调用了父类的构造函数并重写了父类的两个方法,分别是用来构建请求体和构建一个Ruquest对象的方法,具体在什么时候调用会在后面进行分析,进入父类 OkHttpRequest

public abstract class OkHttpRequest{    protected String url;    protected Object tag;    protected Map<String, String> params;    protected Map<String, String> headers;    protected int id;    protected Request.Builder builder = new Request.Builder();    protected OkHttpRequest(String url, Object tag,                            Map<String, String> params, Map<String, String> headers,int id)    {        this.url = url;        this.tag = tag;        this.params = params;        this.headers = headers;        this.id = id ;        if (url == null)        {            Exceptions.illegalArgument("url can not be null.");        }        initBuilder();    }    //省略若干代码}

可以看到 OkHttpRequest 对象也是个抽象类这意味着它的所有操作只能交由子类进行调用,可以看到 OkHttpRequest 对象声明了请求所需参数的字段并在构造函数中为它们赋值同时调用了 initBuilder 方法。进去看看

/**     * 初始化一些基本参数 url , tag , headers     */    private void initBuilder()    {        builder.url(url).tag(tag);        appendHeaders();    }

通过鸿洋的注释已经可以很明白这个函数的作用了,此时已经通过OkHttp的Request对象的内部类Builder构建了一条请求但是还没有创建Request对象,那么在哪里创建了呢? 后面揭晓

还记得前面所说的 RequestCall 对象吗! 它是通过 OkHttpReqeust 对象中的build方法产生的,可以看到在build方法中创建了 RequestCall对象并将 OkHttpRequest 对象的上下文环境传入

public abstract class OkHttpRequest{    //省略若干代码...     public RequestCall build()    {        //可以看到在这里会把 OkHttpRequest 类型的上下文传入        return new RequestCall(this);    }    //省略若干代码...}

由于OkHttpRequest是个抽象类,所以build 方法会被它的子类 GetRequest 对像调用并返回 RequestCall 对象,而调用了 OkHttpRequest 对象的 build 方法后执行一个GET请求所需的条件已经初始化完成了,就剩下execute 了! 那么现在再看下面这段代码是不是就很清晰了

public class  GetBuilder extends OkHttpRequestBuilder<GetBuilder> implements HasParamsable{    @Override    public RequestCall build()    {        if (params != null)        {            url = appendParams(url, params);        }        return new GetRequest(url, tag, params, headers,id).build();    }}

小结

经过上面的一些分析一个 GET 请求的构建已经完成的差不多了就差execute了,下面我们来简单的梳理一下

首先通过OkHttpUtils对象的 get 方法获取一个 GetBuilder 对象, GetBuilder 做了这么几件事在build方法中通过GetRequest 初始化了请求参数(注意此时并未生成 OkHttp 的 Request 对象),并返回一个RequestCall 对象,至此已经到了最后一步调用 RequestCall 中的 execute 方法发起请求 !

4.2、最后一步 —— execute

在分析execute方法之前我想先讲讲一个很重要的接口那就是CallBack

public abstract class Callback<T>{    //UI Thread    public void onBefore(Request request, int id)    {    }    //UI Thread    public void onAfter(int id){    }    //UI Thread    public void inProgress(float progress, long total , int id){    }    /**     * if you parse reponse code in parseNetworkResponse, you should make this method return true.     * 验证响应吗来判断请求是否成功,成功则返回 true     * @param response     * @return     */    public boolean validateReponse(Response response, int id)    {        return response.isSuccessful();    }    /**     * Thread Pool Thread     *     * @param response     */    public abstract T parseNetworkResponse(Response response, int id) throws Exception;    public abstract void onError(Call call, Exception e, int id);    public abstract void onResponse(T response, int id);    public static Callback CALLBACK_DEFAULT = new Callback()    {        @Override        public Object parseNetworkResponse(Response response, int id) throws Exception        {            return null;        }        @Override        public void onError(Call call, Exception e, int id)        {        }        @Override        public void onResponse(Object response, int id)        {        }    };}

可以看到 CallBack 为我们提供了请求过程中的一系列方法,并且内部提供了一个默认的 CallBack 实例可以直接使用 其中有一个方法需要大家注意那就是 parseNetworkResponse 这个方法,相信自定义过 CallBack 的童鞋一定不陌生,这个方法是必需要实现的,就用鸿洋 sample 中的例子简单说下。

大家都知道我们在发送一条请求后,服务器会给出相应的数据,通常是一堆字符串或者一个流,可是如果我们想让其返回特定的类型呢? 用鸿洋定义CallBack对象可以很轻松的实现这个过程,简单来说分为两步:

首先创建一个抽象类继承CallBack 对象指定相应的泛型类型并实现 parseNetworkResponse 方法,在里面完成对数据的转换

public abstract class UserCallback extends Callback<User>{    @Override    public User parseNetworkResponse(Response response, int id) throws IOException    {        String string = response.body().string();        //获取数据后转换成自己想要的类型        User user = new Gson().fromJson(string, User.class);        return user;    }}

然后在execute方法中创建自定义的CallBack对象就行了,可以看到这个时候返回的 Response 就是你自定义的类型了

OkHttpUtils//      .post()//      .url(url)////    .params(params)//      .build()//      .execute(new UserCallback()//      {          @Override          public void onError(Call call, Exception e, int id)          {              mTv.setText("onError:" + e.getMessage());          }          @Override          public void onResponse(User response, int id)          {              mTv.setText("onResponse:" + response);          }      });

对CallBack了解后我们继续分析RequestCall 对象中的 execute 方法

execute这个方法位于 RequestCall 这个对象中,那么这个类是干嘛的? 看看鸿洋对这个类的简单描述:

对OkHttpRequest的封装,对外提供更多的接口:cancel(),readTimeOut()...

通过注释可以知道这些对外接口可以为单独的一条请求单独的配置 timeout,也可以取消一个请求等等… , 上代码看看

public class RequestCall{    private OkHttpRequest okHttpRequest;    private Request request;    private Call call;    private long readTimeOut;    private long writeTimeOut;    private long connTimeOut;    private OkHttpClient clone;    public RequestCall(OkHttpRequest request)    {        this.okHttpRequest = request;    }    public RequestCall readTimeOut(long readTimeOut)    {        this.readTimeOut = readTimeOut;        return this;    }    public RequestCall writeTimeOut(long writeTimeOut)    {        this.writeTimeOut = writeTimeOut;        return this;    }    public RequestCall connTimeOut(long connTimeOut)    {        this.connTimeOut = connTimeOut;        return this;    }    //构建 OkHttp 包下的Call 对象    public Call buildCall(Callback callback)    {        request = generateRequest(callback);        if (readTimeOut > 0 || writeTimeOut > 0 || connTimeOut > 0)        {            readTimeOut = readTimeOut > 0 ? readTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS;            writeTimeOut = writeTimeOut > 0 ? writeTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS;            connTimeOut = connTimeOut > 0 ? connTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS;            clone = OkHttpUtils.getInstance().getOkHttpClient().newBuilder()                    .readTimeout(readTimeOut, TimeUnit.MILLISECONDS)                    .writeTimeout(writeTimeOut, TimeUnit.MILLISECONDS)                    .connectTimeout(connTimeOut, TimeUnit.MILLISECONDS)                    .build();            call = clone.newCall(request);        } else        {            call = OkHttpUtils.getInstance().getOkHttpClient().newCall(request);        }        return call;    }    private Request generateRequest(Callback callback)    {        return okHttpRequest.generateRequest(callback);    }    //执行请求的方法    public void execute(Callback callback)    {        buildCall(callback);        if (callback != null)        {            callback.onBefore(request, getOkHttpRequest().getId());        }        OkHttpUtils.getInstance().execute(this, callback);    }    //获取OkHttp 的Call 对象    public Call getCall()    {        return call;    }    //获取 OkHttp 的 Request 对象    public Request getRequest()    {        return request;    }    public OkHttpRequest getOkHttpRequest()    {        return okHttpRequest;    }    public Response execute() throws IOException    {        buildCall(null);        return call.execute();    }    //取消请求    public void cancel()    {        if (call != null)        {            call.cancel();        }    }}

这些代码相信看起来没有难度,基本都可以见名知意所以不多说了

下面我们来重点看看 execute 方法代码如下

public void execute(Callback callback)    {        buildCall(callback);        if (callback != null)        {            callback.onBefore(request, getOkHttpRequest().getId());        }        OkHttpUtils.getInstance().execute(this, callback);    }

可以看到execute需要传入一个 CallBack(鸿洋定义的请求结果回调接口) 对象,并且内部做了这么几件事,通过 buildCall 方法构建 Okhttp 的 Call 对象,对callback进行了非空判断并调用了 onBefore 方法(请求开始时调用的方法),最终通过OkHttpUtils.class 中的execute方法执行了请求

看着没几行其实背后做了不少事,首先进入 buildCall(callback); 这个方法中看看干了什么

 public Call buildCall(Callback callback)    {        //生成 OkHttp 的Request 对象        request = generateRequest(callback);        //判断用户是否为单个请求设置超时时间        if (readTimeOut > 0 || writeTimeOut > 0 || connTimeOut > 0)        {            readTimeOut = readTimeOut > 0 ? readTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS;            writeTimeOut = writeTimeOut > 0 ? writeTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS;            connTimeOut = connTimeOut > 0 ? connTimeOut : OkHttpUtils.DEFAULT_MILLISECONDS;            //获取OkHttpClient 对象为单独的请求设置超时时间            clone = OkHttpUtils.getInstance().getOkHttpClient().newBuilder()                    .readTimeout(readTimeOut, TimeUnit.MILLISECONDS)                    .writeTimeout(writeTimeOut, TimeUnit.MILLISECONDS)                    .connectTimeout(connTimeOut, TimeUnit.MILLISECONDS)                    .build();            //通过Request对象构建一个Call对象(注意是 OkHttp 中的 Call 对象)            call = clone.newCall(request);        } else        {             //如果没有设置则直接生成Call对象            call = OkHttpUtils.getInstance().getOkHttpClient().newCall(request);        }        return call;    }

注释已经写得很清楚了所以就不啰嗦了!

可以看到这个方法做了两件事:

  • 生成OkHttp的Reqeust对象
  • 返回OkHttp 的Call 对象

我们看看OkHttp的Reqeust对象是怎么通过 generateRequest(callback) 这个方法生成的,点进去看看

private Request generateRequest(Callback callback){        return okHttpRequest.generateRequest(callback);}

很简单调用了 OkHttpRequest 对象中的 generateRequest(callback) 方法,继续点进去

public Request generateRequest(Callback callback){       RequestBody requestBody = buildRequestBody(); //GetBuilder中 实现的抽象方法       RequestBody wrappedRequestBody = wrapRequestBody(requestBody, callback);       Request request = buildRequest(wrappedRequestBody);//GetBuilder中 实现的抽象方法       return request;   }

通过上面的代码可以看到生成一个 oKHttp 的 Request 对象主要分为三步

  • 构建请求体
  • 包装请求体(主要是下载文件的时候计算百分比并通过 CallBack 的 inProgress 方法进行回调)
  • 构建 OkHttp 的 Request

如果你挨个把其中的三个步骤方法都点进去,你会发现 buildRequestBody() 返回的是 null ,所以对应的wrapRequestBody(requestBody, callback) 方法肯定返回的也是 null , 而在 buildRequest(wrappedRequestBody) 方法中会通过在 OkHttpRequest 中的 Request.Builder 对象构建真正的 Request 对象,具体代码就不贴了感兴趣的可以自己看看

这里插两句嘴,为什么 buildRequestBody() 返回的是 null 呢? 很简单 GET 请求是不需要 requestBody 的,所以就返回 null 喽,只有 post 请求并且有参数的情况下才会返回不为空的 requestBody,所以 GET 请求默认返回的都是 null

啰嗦了一大堆! 几经周转最终还是回到了 OkHttpUtils 这个类中的execute方法,这也是真正执行请求的地方,进去看看

public void execute(final RequestCall requestCall, Callback callback){     if (callback == null)         callback = Callback.CALLBACK_DEFAULT;     final Callback finalCallback = callback;     final int id = requestCall.getOkHttpRequest().getId();    //通过 RequestCall 对象获取 OkHttp 的 Call 对象发起真正的请求     requestCall.getCall().enqueue(new okhttp3.Callback(){         @Override         public void onFailure(Call call, final IOException e)         {             sendFailResultCallback(call, e, finalCallback, id);         }         @Override         public void onResponse(final Call call, final Response response)         {             try             {                 if (call.isCanceled())                 {                     sendFailResultCallback(call, new IOException("Canceled!"), finalCallback, id);                     return;                 }                 if (!finalCallback.validateReponse(response, id))                 {                     sendFailResultCallback(call,                             new IOException("request failed                              , reponse's code is : " +    response.code()), finalCallback, id);                     return;                 }                //调用 parseNetworkResponse 方法返回指定的类型对象                 Object o = finalCallback.parseNetworkResponse(response, id);                 //然后将 parseNetworkResponse 返回的对象传入以下方法,                 //这也是为什么在自定义的CallBcak中可以返回自己想要的类型                 sendSuccessResultCallback(o, finalCallback, id);             } catch (Exception e)             {                 sendFailResultCallback(call, e, finalCallback, id);             } finally             {                 if (response.body() != null)                     response.body().close();             }         }     });    }public void sendFailResultCallback(final Call call, final Exception e, final Callback callback, final int id)    {        if (callback == null) return;        //开启一个缓存线程池异步调用对应的 callback 方法        mPlatform.execute(new Runnable()        {            @Override            public void run()            {                callback.onError(call, e, id);                callback.onAfter(id);            }        });    }public void sendSuccessResultCallback(final Object object, final Callback callback, final int id)    {        if (callback == null) return;        //开启一个缓存线程池异步调用对应的 callback 方法        mPlatform.execute(new Runnable()        {            @Override            public void run()            {                callback.onResponse(object, id);                callback.onAfter(id);            }        });    }

ok,我们顺着代码缕缕! execute 方法接收两个参数

第一个参数不用多说是 RequestCall 对象

第二个参数是鸿洋提供 CallBack 接口

首先在方法内部会判断 Callback 是否为空如果为空则使用默认 CallBack,然后通过传入的 RequestCall 获取请求的 ID 这个 id 还是很有用处的可以通过这个id来判断是哪一个请求,接下来再通过 RequestCall 对象获取 OkHttp 的 Call 对象发起 enqueue 异步请求,至于请求失败或者成功鸿洋也通过传入的 Callback 接口进行了回调,具体细节看看 onFialure 和 onResponse 就会明白了!

下面我们再来回顾一个标准的GET请求

OkHttpUtils    .get()//获取 XXXBuilder 对象    .url(url)//添加参数    .addParams("username", "hyman")//添加参数    .addParams("password", "123")//添加参数    .build()// 返回 ReqeustCall 对象    .execute(new StringCallback()//调用ReqeustCall的execute            {                @Override                public void onError(Request request, Exception e)                {                }                @Override                public void onResponse(String response)                {                }            });

怎么样是不是觉得整个请求构建过程都清晰明了了 !

ok ! 到此一个完整 GET 请求流程就完成了!

5、总结

让我们在最后对整个流程进行一个总结

当 OkHttpUtils.class 在 application 中初始化后,发起一个 GET 请求会经过如下几个步骤

  • 通过OkHttpUtils对象获取一个 XXXBuidler 对象
  • 通过XXXBuidler对象添加完请求所需参数后调用 builde 对象创建一个 XXXRequest 对象来初始化参数,并通过 XXXRequest 对象的 build方法(其实最终调用的还是父类 OkHttpRequest 对象的build方法) 返回一个 RequestCall 对象
  • 调用 RequestCall 对象中的 execute 方法来发起一个请求

可以看到总体的调用和构建流程很清晰:

通过 XXXBuilder 添加参数 —> XXXRequest 初始化参数并返回 RequestCall 对象 —> RequesCall 生成 OkHttp 的 Request 然后调用 OkHttpUtils 对象的 execute 方法发起请求

可以看到鸿洋的 OKHttpUtils 的的封装过程还是很简单的,水平有限可能有些地方分析的不到位,如果你认为哪里不对欢迎留言! 我会及时改正!(你想多了,谁闲的没事看你这玩意!/(ㄒoㄒ)/~~)

6、写在最后

至于POST请求的流程就留给感兴趣的读者自己分析吧,跟 GET 的流程是一样的,只是有些许细节不同而已,所以就不写了!

学习是痛苦而愉悦的,从看不下去到后来的逼着自己静下心慢慢看才发现好像也没那么难! 当然 OkHttpUtils 这个框架的整体设计也不复杂所以也有看下去的动力! 在里面也学到不少经验,比如模板模式和Buidler 模式的使用,还有一些封装的思想! 嗯,总体感觉还不错。

第一篇博客就这么愉快的写完了! 再接再厉,继续保持 oh yeah ~~ 学习ing

参考文章与源码

鸿洋博客
OkHttpUtils 源码

原创粉丝点击