1. 框架功能简介:暂时只有get、post两个请求

2. 请求的主要流程和区别:

2.1 get请求:

(1)创建请求客户的 OkHttpClient对象

(2)创建请求构建器 Request.Bulder builder = new Request.Builder().url(...). build();

(3)创建请求对象:Request request = builder.build();

(3)创建请求任务 Call call

(4)发起异步请求:call.enqueue(new CallBack(){...});

2.2 post请求

(1)创建请求客户的 OkHttpClient对象

(2)创建请求构建器 Request.Builder builder = new Request.Builder().url(...). build();

(3)创建表单实体构建器:FormBody.Builder mFormBuilder

(4)创建表单实体对象:FormBody body

(5)创建请求对象:Request request = builder.post(body);

(6)创建请求任务:Call call

(7)发起异步任务:call.enqueue(new CallBack(){...});

2.3 两者区别

请求构建器 builder 与请求对象request之间,post需要创建请求实体,并在请求实体中添加参数——封装的框架需要考虑两者区别,处理好复用代码和分别处理

3. 代码

/**

*OkHttp的二次封装

*get请求、post请求

* 客户端异步发起请求,(url(), targetClass(), 调用接口等)——OkUtils通过Handler返回结果

*/

public class OkUtils<T>{

  private static final String UTF_8 = "utf-8";

  private static final int RESULT_SUCCESS = 0;

  private static final int RESULT_ERROR =1;

  private StringBuilder mUrl;

  private OkHttpClient mOkHttpClient; // 单例模式

  private Handler mHandler;

  private OnCompleteListener<T> mListener;

  // 地址栏请求

  private StringBuilder mUrl;

  // 泛型,目标解析类

  private Class mClaz;

  // post表单body构造器

  private FromBody.Builder mFormBuilder;

  

  // 对外提供接口:客户端向服务端发送请求、处理返回结果的接口

  public interface OnCompleteListener<T>{

    void onSuccess(T t);

    void onError(String error);

  }

  // 构造方法,单例模式初始化mOkHttpClient

  pubic OkUtils(Context context){// 注意参数要有

    if(mOkHttpClient == null){

      synchronized(OkUtils.class){

        if(mOkHttpClient == null){

          mOkHttpClient = new OkHttpClient();

        }

      }

    }

    initHandler(context);

  }

  private void initHandler(Context context){

    mHandler = new Handler(context.getMainLooper){

      @override

      public void handleMessage(Message msg){

        super.handleMessage(msg);

        switch(msg.what){

          case RESULT_SUCCESS:

            if(mListener != null && msg.obj != null){

              T t = (T) mst.obj;        

              mListener.onSuccess(t);

            }       

            break;

          case RESULT_ERROR:

            if(mListener != null && msg.obj != null){

              mListener.onError(msg.obj.toString());

            }         

            break;

        }

      }

    };

  }

  // 地址栏请求

  public OkUtils<T> url(StringBuilder url){

    mUrl = new StringBuilder(url);

    return this;

  }

  // 创建post表单body构建器

  public OkUtils<T> post(){

    mFormBuilder = new FormBody.Builder();

    return this;

  }

  // 目标解析类

  public OkUtils<T> targetClass(Class claz){

    mClaz = claz;

  }

  // 添加参数

  public OkUtils<T> addParam(String key, String value){

    if(mFormBuilder != null){ // post请求的参数添加方式

      mFormBuilder.add( key, URLEncoder.encode(value, UTF_8));

    }else{// get请求的参数添加方式

      if(mUrl.indexOf("?") == -1){

        mUrl.apend("?");

      }else{

        mUrl.apend("&");

      }

      mUrl.append(key).append("=").append(URLEncoder.encode(value, UTF_8));  // 注意此处需要抛异常,已省略。编辑代码时会遇到。

    }

    return this;

  }

  public void execute(OnCompleteListener listener){

    mListener = listener;

    // 校验 mUrl,参数,mClaz是否符合发送请求的要求

    if( mUrl == null){

      Message msg = Message.obtain();

      msg.what = RESULT_ERROR;

      msg.obj = "url不能为空";

      mHandler.sendEmptyMessage(msg);

      return;

    }

    if( mUrl.indexOf("?" == -1){

      Message msg = Message.obtain();

      msg.what = RESULT_ERROR;

      msg.obj = "请设置请求参数";

      mHandler.sendEmptyMessage(msg);

    }

    if( mClaz == null){

      Message msg = Message.obtain();

      msg.what = RESULT_ERROR;

      msg.obj = "解析目标类claz不能为空";

      mHandler.sendEmptyMessage(msg);

      return;

    }

    // 创建请求构建器

    Request.Builder builder = new Request.Builder().url(mUrl.toString);

    if(mFormBuilder != null){ // post请求,创建表单实体

      FormBody body = mFormBuilder.build();

      builder.post(body);

    }

    Request request = builder.build();

    Call call = mOkHttpClient.newCall(request);

    call.enqueue(new CallBack(){

      @override

      public void onFailure(Call call, IOException e){

        Message msg = Message.obtain();

        msg.what = RESULT_ERROR;

        msg.obj = e.toString();

        mHandler.sendMessage(msg);

      }

      @override

      public void onResponse(Call call, Response response) throws IOExcepton{

        String json = response.body().string();

        T t = (T)ResultUtils.getResultFromJson(json, mClaz); // ResultUtils 是一个工具类,解析json数据,如果需要请留言

        Message msg = Message.obtain();

        msg.what = RESULT_OK;

        msg.obj = t;

        mHandler.sendMessage(msg);

      }

    });

  }

  public static void release(){

    if( mOkHttpClient != null) {

      mOkHttpClient.dispatcher().cancel();

      mOkHttpClient == null;

    }

  }

}

到此,一个基本的OkHttp就封装好了,其他的诸如上传文件、下载文件等功能,下次整理。

二次封装OKHttp网络框架(1)的更多相关文章

  1. Android OKHttp网络框架

    好久没逛简书了.这周公司的项目也已经愉快的迭代了新版本,对于之前一直存留的东西一直没怎么梳理,今天想说说这两年特别火的网络框架.okhttp我想大部分Android开发者都不陌生,因为它的到来.是我们 ...

  2. 开源框架相关面试问题-okhttp网络框架面试问题详解

    OkHttp使用简介: ①.准备OkHttpClient对象: 一般app中使用网络可以全部用它,可以将它弄为全局变量,这样就可以共用它的缓存和线程池了. ②.准备Request对象: 很显然它是采用 ...

  3. 「2020 新手必备 」极速入门 Retrofit + OkHttp 网络框架到实战,这一篇就够了!

    老生常谈 什么是 Retrofit ? Retrofit 早已不是什么新技术了,想必看到这篇博客的大家都早已熟知,这里就不啰嗦了,简单介绍下: Retrofit 是一个针对 Java 和 Androi ...

  4. AFNetworking二次封装的那些事

    AFNetworking可是iOS网络开发的神器,大大简便了操作.不过网络可是重中之重,不能只会用AFNetworking.我觉得网络开发首先要懂基本的理论,例如tcp/ip,http协议,之后要了解 ...

  5. OkGo3.0 --真实项目使用和二次封装(转)

    转载:https://blog.csdn.net/jiushiwo12340/article/details/79011480  11.OkGo3.0真实项目使用和二次封装: ====  11.OkG ...

  6. OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据

    OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据 我们这片博文就来聊聊这个反响很不错的OkHttp了,标题是我恶搞的,本篇将着重详细的 ...

  7. 上门洗车APP --- Androidclient开发 之 网络框架封装介绍(二)

    上门洗车APP --- Androidclient开发 之 网络框架封装介绍(二) 前几篇博文中给大家介绍了一下APP中的基本业务及开发本项目使用的网络架构: 上门洗车APP --- Androidc ...

  8. android基于开源网络框架asychhttpclient,二次封装为通用网络请求组件

    网络请求是全部App都不可缺少的功能,假设每次开发都重写一次网络请求或者将曾经的代码拷贝到新的App中,不是非常合理,出于此目的,我希望将整个网络请求框架独立出来,与业务逻辑分隔开,这样就能够避免每次 ...

  9. 网络框架OKHTTP使用场景全解析

    [本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] 一.引言 说句实 ...

随机推荐

  1. hrbust oj 1536 Leonardo's Notebook 置换群问题

    题目大意: 给出一个A~Z的置换G,问能否找到一个A~Z的置换G' 能够用来表示为 G = G'*G' 由定理: 任意一个长为 L 的置换的k次幂,都会把自己的每一个循环节分裂成gcd(L, K)份, ...

  2. 多项式输出 2009年NOIP全国联赛普及组

    时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold   题目描述 Description 一元 n 次多项式可用如下的表达式表示:数,请按照如下规定的格式要求输出该多项式 ...

  3. HashMap源码分析2:扩容

    本文源码基于JDK1.8.0_45. final Node<K,V>[] resize() { Node<K,V>[] oldTab = table; int oldCap = ...

  4. zabbix全方位监控MySQL +cacti监控mysql

    http://www.linuxidc.com/Linux/2015-02/112690.htm http://john88wang.blog.51cto.com/2165294/1596272?ut ...

  5. css3 字体自适应

    css3提供了一些与当前viewpoint相关的元素,vw,vh,vim等. “viewpoint” = window size vw = 1% of viewport width 1vh = 1% ...

  6. Linux ANSI 乱码问题

    原帖http://blog.chinaunix.net/u/24624/showart_184609.html Windows 到 linux 解决samba-3.x客户端中文乱码问题 dos cha ...

  7. lua中的metatable和metamethod

    --元表和元方法给lua里的值设定一些操作,让我们可以对这些操作自定义 --创建一个新的table变量时,它是不存在元表的 --在Lua中,只能设置table的元表,其他类型的值的元表,只能通过C代码 ...

  8. influxDB系列(二)--查看数据库的大小

    google 搜索了好多文档,终于发现了这个靠谱的回答. https://groups.google.com/forum/#!topic/influxdb/I5eady_Ta5Y You can se ...

  9. C# 生成pdf文件客户端下载

    itextsharp.dll 下载:http://sourceforge.net/projects/itextsharp/ 程序需引用:itextsharp.dll,itextsharp.pdfa.d ...

  10. [BZOJ 1698] 荷叶池塘

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1698 [算法] 最短路 [代码] #include<bits/stdc++.h ...