1,昨天把okHttp仔细的看了一下,以前都是调用同事封装好了的网络框架,直接使用很容易,但自己封装却不是那么简单,还好,今天就来自我救赎一把,就和大家写写从最基础的OKHttp的简单get、post的使用,再到它的封装。

2,OkHttp的简单使用

  首先我们创建一个工程,并在布局文件中添加三个控件,TextView(用于展示获取到json后的信息)、Button(点击开始请求网络)、ProgressBar(网络加载提示框)

  ①简单的异步Get请求

  第一步,创建OKHttpClient对象

  第二步,创建Request请求

  第三步,创建一个Call对象

  第四步,将请求添加到调度中

  不多说,直接上代码:

    //okHttp的基本使用 --- get方法
String url = "https://api.douban.com/v2/movie/top250?start=0&count=10";
//1,创建OKHttpClient对象
OkHttpClient mOkHttpClient = new OkHttpClient();
//2,创建一个Request
Request request = new Request.Builder().url(url).build();
//3,创建一个call对象
Call call = mOkHttpClient.newCall(request);
//4,将请求添加到调度中
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) { } @Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
final String message = response.body().string();
handler.post(new Runnable() {
@Override
public void run() {
tv_message.setText(message);
progressBar.setVisibility(View.GONE);
}
}); }
} });

 效果如下: 

  

  注意,由于我们调用的enqueue()方法,是运行在网络线程中的,所以当我们得到json数据后想要获取更新UI的话,可以开使用handle.post()方法在run方法里面更新UI。

  ② 简单的异步Post请求

  这里的Post请求我们以最常见的注册登录来举例。post请求的步骤和get是相似的只是在创建Request的 时候将服务器需要的参数传递进去.

  代码如下:

 String url = "http://192.168.1.123:8081/api/login";
//1,创建OKhttpClient对象
OkHttpClient mOkHttpClient = new OkHttpClient();
//2,创建Request
RequestBody formBody = new FormEncodingBuilder()
.add("username", "superadmin")
.add("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413")
.build(); Request request = new Request.Builder().url(url).post(formBody).build();
//3,创建call对象并将请求对象添加到调度中
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) { } @Override
public void onResponse(Response response) throws IOException {
Log.i("wangjitao", response.body().string());
}
});

  看一下我们服务器的断点

  

  可以看到我们服务器的确拿到了我们传递参数,再看一下我们请求后拿到的数据

  ok,这样的话我们的post方法就没什么问题了

3,OkHttp的封装

由于是封装我们可以吧OKHttp和Gson给结合起来,那么我们在gradle文件添加以下的依赖

 compile "com.squareup.okhttp:okhttp:2.4.0"
compile 'com.squareup.okio:okio:1.5.0'
compile "com.google.code.gson:gson:2.8.0"

  ①CallBack的创建  

  首选我们知道,当接口请求成功或者失败的时候我们需要将这个信息通知给用户,那么我们就需要创建一个抽象类RequestCallBack,请求前、成功、失败、请求后这几个方法,创建OnBefore()、OnAfter()、OnError()、OnResponse()对应

  

    /**
* 在请求之前的方法,一般用于加载框展示
*
* @param request
*/
public void onBefore(Request request) {
} /**
* 在请求之后的方法,一般用于加载框隐藏
*/
public void onAfter() {
} /**
* 请求失败的时候
*
* @param request
* @param e
*/
public abstract void onError(Request request, Exception e); /**
*
* @param response
*/
public abstract void onResponse(T response);

 由于我们每次想要的数据不一定,所以这里我们用<T>来接收想要装成的数据格式,并通过反射得到想要的数据类型(一般是Bean、List)之类 ,所以RequestCallBack的整体代码如下:

package com.qianmo.httprequest.http;

import com.google.gson.internal.$Gson$Types;
import com.squareup.okhttp.Request; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; /**
* Created by wangjitao on 15/10/16.
* 抽象类,用于请求成功后的回调
*/
public abstract class ResultCallback<T> {
//这是请求数据的返回类型,包含常见的(Bean,List等)
Type mType; public ResultCallback() {
mType = getSuperclassTypeParameter(getClass());
} /**
* 通过反射想要的返回类型
*
* @param subclass
* @return
*/
static Type getSuperclassTypeParameter(Class<?> subclass) {
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
} /**
* 在请求之前的方法,一般用于加载框展示
*
* @param request
*/
public void onBefore(Request request) {
} /**
* 在请求之后的方法,一般用于加载框隐藏
*/
public void onAfter() {
} /**
* 请求失败的时候
*
* @param request
* @param e
*/
public abstract void onError(Request request, Exception e); /**
*
* @param response
*/
public abstract void onResponse(T response);
}

  ②对Get、Post方法的简单封装 

  首先我们创建一个OkHttpClientManager类,由于是管理类,所以,单例加静态对象搞起

 private static OkHttpClientManager mInstance;

  public static OkHttpClientManager getInstance() {
if (mInstance == null){
synchronized (OkHttpClientManager.class) {
if (mInstance == null) {
mInstance = new OkHttpClientManager();
}
}
}
return mInstance;
}

 在创建Manager对象的时候我们要把OkHttp的一些参数配置一下,顺便一提一下,由于我们我们异步get、post方法是运行在子线程中,所以这里我们添加了分发的 Handler mDelivery;,重写的OkHttpClientManager构造方法如下:

 private OkHttpClientManager() {
mOkHttpClient = new OkHttpClient();
mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
//cookie enabled
mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
mDelivery = new Handler(Looper.getMainLooper());
mGson = new Gson();
}

  前面的外部调用对象封装好了,这里我们开始来封装Get或Post方法,我这里以Post方法为例子,首先分析一下,post方法会有几个参数,参数一url,参数二参数params,参数三Callback(及我们上面的RequestCallBack)参数四flag(用于取消请求操作,可为空),基础代码如下:

 /**
* 通用基础的异步的post请求
* @param url
* @param callback
* @param tag
*/
public void postAsyn(String url, Param[] params, final ResultCallback callback, Object tag) {
Request request = buildPostFormRequest(url, params, tag);
deliveryResult(callback, request);
}

  那么我们再看一下deliveryResult方法到底是干什么的

 /**
* 请求回调处理方法并传递返回值
* @param callback Map类型请求参数
* @param request Request请求
*/
private void deliveryResult(ResultCallback callback, Request request) {
if (callback == null)
callback = DEFAULT_RESULT_CALLBACK;
final ResultCallback resCallBack = callback;
//UI thread
callback.onBefore(request);
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(final Request request, final IOException e) {
sendFailedStringCallback(request, e, resCallBack);
} @Override
public void onResponse(final Response response) {
try {
final String responseMessage=response.message();
final String responseBody = response.body().string();
if(response.code()==200){
if (resCallBack.mType == String.class) {
sendSuccessResultCallback(responseBody, resCallBack);
} else {
Object o = mGson.fromJson(responseBody, resCallBack.mType);
sendSuccessResultCallback(o, resCallBack);
}
}else{
Exception exception=new Exception(response.code()+":"+responseMessage);
sendFailedStringCallback(response.request(), exception, resCallBack);
}
} catch (IOException e) {
sendFailedStringCallback(response.request(), e, resCallBack);
} catch (com.google.gson.JsonParseException e) {//Json解析的错误
sendFailedStringCallback(response.request(), e, resCallBack);
}
}
});
}

  可以看到,这个方法主要是发出请求并对请求后的数据开始回调,这样我们就基本上封装好了一个post方法了  ,把代码这一部分的代码贴出来看看

public class OkHttpClientManager {
private static final String TAG = "com.qianmo.httprequest.http.OkHttpClientManager"; private static OkHttpClientManager mInstance;
//默认的请求回调类
private final ResultCallback<String> DEFAULT_RESULT_CALLBACK = new ResultCallback<String>(){
@Override
public void onError(Request request, Exception e) {} @Override
public void onResponse(String response) {}
};
private OkHttpClient mOkHttpClient;
private Handler mDelivery;
private Gson mGson;
private GetDelegate mGetDelegate = new GetDelegate();
private PostDelegate mPostDelegate = new PostDelegate();
private DownloadDelegate mDownloadDelegate = new DownloadDelegate(); private OkHttpClientManager() {
mOkHttpClient = new OkHttpClient();
mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
//cookie enabled
mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
mDelivery = new Handler(Looper.getMainLooper());
mGson = new Gson();
} public static OkHttpClientManager getInstance() {
if (mInstance == null){
synchronized (OkHttpClientManager.class) {
if (mInstance == null) {
mInstance = new OkHttpClientManager();
}
}
}
return mInstance;
} /**
* 外部可调用的Post异步请求方法
* @param url 请求url
* @param params
* @param callback 请求完成后回调类
*/
public static void postAsyn(String url, Map<String, String> params, final ResultCallback callback) {
getInstance().getPostDelegate().postAsyn(url, params, callback, null);
} /**
* 异步的post请求
* @param url
* @param params
* @param callback
* @param tag
*/
public void postAsyn(String url, Map<String, String> params, final ResultCallback callback, Object tag) {
Param[] paramsArr = map2Params(params);
postAsyn(url, paramsArr, callback, tag);
}
/**
* 通用基础的异步的post请求
* @param url
* @param callback
* @param tag
*/
public void postAsyn(String url, Param[] params, final ResultCallback callback, Object tag) {
Request request = buildPostFormRequest(url, params, tag);
deliveryResult(callback, request);
} /**
* 请求回调处理方法并传递返回值
* @param callback Map类型请求参数
* @param request Request请求
*/
private void deliveryResult(ResultCallback callback, Request request) {
if (callback == null)
callback = DEFAULT_RESULT_CALLBACK;
final ResultCallback resCallBack = callback;
//UI thread
callback.onBefore(request);
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(final Request request, final IOException e) {
sendFailedStringCallback(request, e, resCallBack);
} @Override
public void onResponse(final Response response) {
try {
final String responseMessage=response.message();
final String responseBody = response.body().string();
if(response.code()==200){
if (resCallBack.mType == String.class) {
sendSuccessResultCallback(responseBody, resCallBack);
} else {
Object o = mGson.fromJson(responseBody, resCallBack.mType);
sendSuccessResultCallback(o, resCallBack);
}
}else{
Exception exception=new Exception(response.code()+":"+responseMessage);
sendFailedStringCallback(response.request(), exception, resCallBack);
}
} catch (IOException e) {
sendFailedStringCallback(response.request(), e, resCallBack);
} catch (com.google.gson.JsonParseException e) {//Json解析的错误
sendFailedStringCallback(response.request(), e, resCallBack);
}
}
});
}
/**
* 处理请求成功的回调信息方法
* @param object 服务器响应信息
* @param callback 回调类
*/
private void sendSuccessResultCallback(final Object object, final ResultCallback callback) {
mDelivery.post(() -> {
callback.onResponse(object);
callback.onAfter();
});
}
}

  这样我们就把Post方法封装好了,同理Get方法,ok,现在我们可以来调用调用了,在调用之前我们可以对返回数据格式再来封装封装,一般我们后台返回的数据格式是类似如下:

{
"code": 200,
"data": {},
"message": "登录成功"
}

 而data中有可能是对象,也有可能是数组,所以我们用两个类来实现一下

 CommonResultBean

package com.qianmo.httprequest.bean;

/**
* 服务端返回通用接收实体
* Created by wangjitao on 15/10/30.
*/
public class CommonResultBean<T> {
private String code;
private T data;
private String message; public String getCode() {
return code;
} public void setCode(String code) {
this.code = code;
} public T getData() {
return data;
} public void setData(T data) {
this.data = data;
} public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
}
}

 CommonResultListBean

package com.qianmo.httprequest.bean;

import java.util.List;

/**
* 服务端返回带有List数据的通用接收实体
* Created by wangjitao on 15/12/1.
*/
public class CommonResultListBean<T> {
private String code;
private List<T> data;
private String message; public String getCode() {
return code;
} public void setCode(String code) {
this.code = code;
} public List<T> getData() {
return data;
} public void setData(List<T> data) {
this.data = data;
} public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
}
}

  ok,现在还是以上面我们登录的接口为例子开始我们的方法调用,返回的数据格式如图所示

  我们创建UserMenu.java类

package com.qianmo.httprequest.bean;

import java.util.List;

/**
* Created by wangjitao on 2016/12/21 0021.
* E-Mail:543441727@qq.com
* 用户菜单权限按钮
*/
public class UserMenu { /**
* last_login_time : 2016-12-21 15:40:28
* member_id : 1
* modules : []
* phone : 18900532225
* real_name : 超级管理员
* role : {"role_id":1,"role_name":"超级管理员"}
* username : superadmin
*/ private String last_login_time;
private int member_id;
private String phone;
private String real_name;
/**
* role_id : 1
* role_name : 超级管理员
*/ private RoleBean role;
private String username;
/**
* module_code : 100
* module_id : 1
* module_name : 首页
* pid : 0
* type : 1
* value : P_index
*/ private List<ModulesBean> modules; public String getLast_login_time() {
return last_login_time;
} public void setLast_login_time(String last_login_time) {
this.last_login_time = last_login_time;
} public int getMember_id() {
return member_id;
} public void setMember_id(int member_id) {
this.member_id = member_id;
} public String getPhone() {
return phone;
} public void setPhone(String phone) {
this.phone = phone;
} public String getReal_name() {
return real_name;
} public void setReal_name(String real_name) {
this.real_name = real_name;
} public RoleBean getRole() {
return role;
} public void setRole(RoleBean role) {
this.role = role;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public List<ModulesBean> getModules() {
return modules;
} public void setModules(List<ModulesBean> modules) {
this.modules = modules;
} public static class RoleBean {
private int role_id;
private String role_name; public int getRole_id() {
return role_id;
} public void setRole_id(int role_id) {
this.role_id = role_id;
} public String getRole_name() {
return role_name;
} public void setRole_name(String role_name) {
this.role_name = role_name;
}
} public static class ModulesBean {
private String module_code;
private int module_id;
private String module_name;
private int pid;
private int type;
private String value; public String getModule_code() {
return module_code;
} public void setModule_code(String module_code) {
this.module_code = module_code;
} public int getModule_id() {
return module_id;
} public void setModule_id(int module_id) {
this.module_id = module_id;
} public String getModule_name() {
return module_name;
} public void setModule_name(String module_name) {
this.module_name = module_name;
} public int getPid() {
return pid;
} public void setPid(int pid) {
this.pid = pid;
} public int getType() {
return type;
} public void setType(int type) {
this.type = type;
} public String getValue() {
return value;
} public void setValue(String value) {
this.value = value;
}
} }

  所以MainActivity代码如下:

package com.qianmo.httprequest;

import android.os.Environment;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView; import com.qianmo.httprequest.bean.CommonResultBean;
import com.qianmo.httprequest.bean.UserMenu;
import com.qianmo.httprequest.http.IRequestCallBack;
import com.qianmo.httprequest.http.IRequestManager;
import com.qianmo.httprequest.http.OkHttpClientManager;
import com.qianmo.httprequest.http.RequestFactory;
import com.qianmo.httprequest.http.ResultCallback;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response; import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map; public class MainActivity extends AppCompatActivity implements OnClickListener {
private Handler handler;
private TextView tv_message;
private Button btn_login;
private ProgressBar progressBar; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_message = (TextView) findViewById(R.id.tv_message);
btn_login = (Button) findViewById(R.id.btn_login);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
handler = new Handler();
btn_login.setOnClickListener(this);
} @Override
public void onClick(View view) {
progressBar.setVisibility(View.VISIBLE); String url = "http://192.168.1.123:8081/api/login";
Map<String, String> params = new HashMap();
params.put("username", "superadmin");
params.put("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413");
OkHttpClientManager.postAsyn(url, params,
new ResultCallback<CommonResultBean<UserMenu>>() {
@Override
public void onError(Request request, Exception e) { } @Override
public void onResponse(CommonResultBean<UserMenu> response) {
if (response.getData() != null) {
UserMenu userMenu = response.getData();
tv_message.setText(userMenu.getReal_name());
progressBar.setVisibility(View.GONE);
}
}
}); }
}

  这样我们就可以简单的调用了,最后看一下我们的效果:

 See You Next Time···

 

  

 

  

Android -- OkHttp的简单使用和封装的更多相关文章

  1. Android okHttp网络请求之Json解析

    前言: 前面两篇文章介绍了基于okHttp的post.get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率? okHttp相关文章地址: Android o ...

  2. Android okHttp网络请求之Get/Post请求

    前言: 之前项目中一直使用的Xutils开源框架,从xutils 2.1.5版本使用到最近的xutils 3.0,使用起来也是蛮方便的,只不过最近想着完善一下app中使用的开源框架,由于Xutils里 ...

  3. Android okHttp网络请求之Retrofit+Okhttp+RxJava组合

    前言: 通过上面的学习,我们不难发现单纯使用okHttp来作为网络库还是多多少少有那么一点点不太方便,而且还需自己来管理接口,对于接口的使用的是哪种请求方式也不能一目了然,出于这个目的接下来学习一下R ...

  4. Android OkHttp完全解析 --zz

    参考文章 https://github.com/square/okhttp http://square.github.io/okhttp/ 泡网OkHttp使用教程 Android OkHttp完全解 ...

  5. Android OkHttp完全解析 是时候来了解OkHttp了

    Android OkHttp完全解析 是时候来了解OkHttp了 标签: AndroidOkHttp 2015-08-24 15:36 316254人阅读 评论(306) 收藏 举报  分类: [an ...

  6. [转] Android OkHttp完全解析 是时候来了解OkHttp了

    http://blog.csdn.net/lmj623565791/article/details/47911083: 本文出自:[张鸿洋的博客] 一.概述 最近在群里听到各种讨论okhttp的话题, ...

  7. Android OkHttp详解

    来源 http://frodoking.github.io/2015/03/12/android-okhttp/ 编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技 ...

  8. Android Okhttp POST提交键值对

    以前的项目网络连接那块一直坚持使用HttpClient,总是会出现一些莫名奇妙的问题,现在新的项目使用了OKHttp网络框架,发现超级好用,上网再了解下,发现OkHttp口碑真的不错,对比之下Http ...

  9. Android okHttp网络请求之缓存控制Cache-Control

    前言: 前面的学习基本上已经可以完成开发需求了,但是在项目中有时会遇到对请求做个缓存,当没网络的时候优先加载本地缓存,基于这个需求我们来学习一直okHttp的Cache-Control. okHttp ...

随机推荐

  1. BZOJ3252: 攻略

    Description 题目简述:树版[k取方格数]   众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景 ...

  2. C#怎样通过url调用接口

    在做一些项目过程中,我们常常总避免不了要调用接口,那么怎么通过url调用借口呢.我今天浅显的写一下. 首先要获取你访问链接的App Key 和 App Secret 那么什么是App Key 和 Ap ...

  3. 02.JavaScript基础上

    JavaScript组成 ECMAScript:解释器.翻译 .平时我们写的代码都是用英文数字之类,而计算机只能读懂0和1,ECMAScript可以把我们写的翻译给计算机,把计算机写的传达给我们DOM ...

  4. *HDU1285 拓扑排序

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  5. 删除 TOMCAT 上次关闭遗留下来的 SESSION 缓存

    参考:删除缓存SESSION 找到tomcat目录下文件:%tomcat home%/conf/context.xml,在标签<Resource>前添加 <Manager pathn ...

  6. js入门篇之Math对象

    Math对象用于执行数学任务 Math对象的属性: Math对象的方法: 常用属性和方法: Math.PI ----------------返回圆周率3.14 ... Math.ceil(x) --- ...

  7. git add 命令

    git add xx命令可以将xx文件添加到暂存区,如果有很多改动可以通过 git add -A .来一次添加所有改变的文件. 注意 -A 选项后面还有一个句点. git add -A表示添加所有内容 ...

  8. java并发编程(二)线程中断

    参考:http://blog.csdn.net/ns_code/article/details/17091267 使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thre ...

  9. Swift与OC混编

    OC调用Swift的方法:添加 import "xxxx-Swift.h" 头文件即可 Swift调用OC的方法:需要建立桥接: xxxx-Bridging-Header.h 头文 ...

  10. <meta>指定浏览器模式(browser mode)或文档模式(document mode)无效

    这是前两天解决的一个故障,准确的说它不是一个SharePoint的问题,而是IE8浏览器或者说是HTML代码的问题,但我感觉还是挺有意思的,所以贴上来分享一下. 基础知识 简单的讲,就是IE浏览器中有 ...