1.简意:OKHttp是一个高效的Http库
2.优点:
(1)支持SPDY,共享同一个Socket来处理同一个服务器的所有请求
(2)如果SPDY不可用,则通过连接池来减少请求延时
(3)无缝的支持GZIP来减少数据流量
(4)缓存响应数据来减少重复的网络请求
3.支持情况:
(1)一般的get请求
(2)一般的post请求
(3)基于Http的文件上传
(4)文件下载
(5)加载图片
(6)支持请求回调,直接返回对象和对象集合
(7)支持session的保持
4.基本使用步骤:
(1)在gradle中引入依赖库:
compile 'com.squareup.okhttp:okhttp:2.7.2'
(2)Http Get请求:
private Object getDataFromUrl(String strUrl) {
//(1)创建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
//(2)new 一个Request.Builder(),并设置其url(字符串),和build()方法
Request request = new Request.Builder()
.url(strUrl)
.build();
try {
//(3)调用client.newCall(request对象).execute()方法,返回一个Response对象
//这里要进行异常处理
//execute()是同步处理
Response response = client.newCall(request).execute();
//(4)调用response.isSuccessful()方法判断返回是否成功
if(response.isSuccessful()) {
//(5)调用response.body().xxx()方法返回相应数据
return response.body().string();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
但,execute()方法时同步操作,故而可调用其异步操作:enqueue()方法:
private void getDataFromUrl(String strUrl) {
//(1)创建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
//(2)new 一个Request.Builder(),并设置其url(字符串),和build()方法
Request request = new Request.Builder()
.url(strUrl)
.build();
//(3)调用client.newCall(request对象).enqueue(new Callback(){})方法
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
}
@Override
public void onResponse(Response response) throws IOException {
//(4)处理数据
response.body().string();
}
});
}
如:例子1:获取网络一张图片并显示出来:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/test_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
测试类:
public class TestActivity extends AppCompatActivity {
private ImageView mImageView; //定义图片
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
findViewID(); //绑定id
requestImage(); //请求图片
}
/**
* 为控件绑定id
*/
private void findViewID() {
mImageView = (ImageView) this.findViewById(R.id.test_img);
}
/**
* 请求图片
*/
private void requestImage() {
//图片网址
String mUrl = "http://p2.so.qhimgs1.com/t011b5b943d48cb7aae.jpg";
//(1)创建OKHttpClient对象
OkHttpClient client = new OkHttpClient();
//(2)new 一个Request.Builder()对象,并设置url,和执行build()方法
Request request = new Request.Builder()
.url(mUrl)
.build();
//(3)调用client.newCall(request).enqueue(new Callback(){})方法
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
Log.d("TestActivity", " requestFaiure");
}
@Override
public void onResponse(Response response) throws IOException {
Log.d("TestActivity", " requestFaiure");
//获取输入流对象
InputStream is = response.body().byteStream();
//转化为Bitmap对象
Bitmap bitmap = BitmapFactory.decodeStream(is);
//为控件设置图片
mImageView.setImageBitmap(bitmap);
}
});
}
}
记得添加网络权限,然后一张美女图就出来了
(3)Http Post请求:
与Get类似,只是在创建OKHttpClient之后,需要创建一个RequestBody对象:
RequestBody body = new FormEncodingBuilder()
.add("type", "1")
.build();
其中:add()可以有多个,即:参数名和参数值
如某个数据网址为:http://www.xxxxx.list?type=1
另一个数据网址为:http://www.xxxxx.list?type=2
......
这时就可以定义String strUrl = "http://www.xxxxx.list"
然后:
RequestBody body = new FormEncodingBuilder()
.add("type", "1")
.add("type", "2")
.build();
就把这两个数据都添加了
记得还要在Request.Builder()添加post(body)
Request request = new Request.Builder()
.url(strUrl)
.post(body)
.build();
其它与get相同即可
(4)我们还可以利用handler在onResponse()方法中进行结果回传:
@Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
Message msg = new Message();
msg.what = 1;
msg.obj = response.body().string();
mHandler.sendMessage(msg);
}
}
二,OkHttp的简单封装:
(1)使用单例模式
(2)对get和post方法进行封装(把共同代码抽出来封装)
(3)对外公开静态方法:如post,get
(4)Callback基类,对OKHttp的回调进行封装。
这个类用里面有一个type,是方便回调中使用Gson对JSON进行解析的封装。
使用Callback的时候只需要在泛型中传入类似Data 、List<Data>即可以方便地使用JSON。
(5)由于原来的回调不在主线程,因此我们需要使用Handler来将回调放入主线程。
例子:
/**OkHttpClient类的封装
* Created by maiyu on 2017/2/25.
*/
/**
* 这个类用来辅助OKHttp
*/
public class OkHttpHelper {
private static OkHttpHelper mOkHttpHelperInstance; //定义OkHttpHelper对象
private static OkHttpClient mClientInstance; //定义OkHttpClient对象
private Handler mHandler; //定义Handler对象
private Gson mGson; //定义Gson对象
/**
* 单例模式,私有构造函数,构造函数里面进行一些初始化
*/
private OkHttpHelper() {
//初始化OkHttpClient对象
mClientInstance = new OkHttpClient();
//设置连接超时,读取超时,写入超时
mClientInstance.setConnectTimeout(10, TimeUnit.SECONDS);
mClientInstance.setReadTimeout(10, TimeUnit.SECONDS);
mClientInstance.setWriteTimeout(30, TimeUnit.SECONDS);
//初始化Gson对象
mGson = new Gson();
//初始化Handler对象:传入Looper.getMainLooper
mHandler = new Handler(Looper.getMainLooper());
}
/**
* 获取实例
* @return
*/
public static OkHttpHelper getInstance() {
//判空
if (mOkHttpHelperInstance == null) {
synchronized (OkHttpHelper.class) {
if (mOkHttpHelperInstance == null) {
//初始化OkHttpHelper的实例
mOkHttpHelperInstance = new OkHttpHelper();
}
}
}
return mOkHttpHelperInstance;
}
/**
* 封装一个request方法:以供get和post调用
*/
public void request(final Request request, final BaseCallback callback) {
//在请求之前所做的事,比如弹出对话框等
// callback.onBeforeRequest(request);
//调用OkHttpClient的newCall(request).enqueue方法,去重写
mClientInstance.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
//返回失败的处理
callbackFailure(request, callback, e);
}
@Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
//返回成功回调:这里可以添加我们需要常用数据类型,如字符串
String resString = response.body().string();
if (callback.mType == String.class) {
//如果我们需要返回String类型
callbackSuccess(response, resString, callback);
} else {
//如果返回的是其他类型,则利用Gson去解析
try {
//获取Object对象o
Object o = mGson.fromJson(resString, callback.mType);
callbackSuccess(response, o, callback);
} catch (JsonParseException e) {
e.printStackTrace();
callbackError(response, callback, e);
}
}
} else {
//返回错误
callbackError(response, callback, null);
}
}
});
}
/**
* 在主线程中执行的回调
*
* @param response
* @param o
* @param callback
*/
private void callbackSuccess(final Response response, final Object o, final BaseCallback callback) {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onSuccess(response, o);
}
});
}
/**
* 在主线程中执行的回调
* @param response
* @param callback
* @param e
*/
private void callbackError(final Response response, final BaseCallback callback, final Exception e) {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onError(response, response.code(), e);
}
});
}
/**
* 在主线程中执行的回调
* @param request
* @param callback
* @param e
*/
private void callbackFailure(final Request request, final BaseCallback callback, final Exception e) {
//发送一个Handler对象
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure(request, e);
}
});
}
/**
* get请求方法
*
* @param url
* @param callback
*/
public void get(String url, BaseCallback callback) {
//get请求,不需要.post(body)---null
Request request = buildRequest(url, null, HttpMethodType.GET);
request(request, callback);
}
/**
* post请求方法
* @param url
* @param params :body组合
* @param callback
*/
public void post(String url, Map<String, String> params, BaseCallback callback) {
//根据url,body数据,和post标志发送请求得到,Request对象
Request request = buildRequest(url, params, HttpMethodType.POST);
request(request, callback); //request请求
}
/**
* 根据type:判断是get还是post请求
* 构建请求对象
* @param url
* @param params
* @param type
* @return
*/
private Request buildRequest(String url, Map<String, String> params, HttpMethodType type) {
//创建Request.Builder对象
Request.Builder builder = new Request.Builder();
//为builder添加url
builder.url(url);
if (type == HttpMethodType.GET) {
builder.get(); //get请求
} else if (type == HttpMethodType.POST) {
//post请求需要先post(body)
builder.post(buildRequestBody(params));
}
return builder.build(); //返回builder.build
}
/**
* 通过Map的键值对构建请求对象的body
*即:post请求需要为builder添加body
* @param params
* @return
*/
private RequestBody buildRequestBody(Map<String, String> params) {
//创建FormEncodingBuilder对象
FormEncodingBuilder builder = new FormEncodingBuilder();
//遍历要传入的Map<String,String>组合,添加到body中去
if (params != null) {
for (Map.Entry<String, String> entity : params.entrySet()) {
builder.add(entity.getKey(), entity.getValue());
}
}
return builder.build(); //返回builder.build()方法
}
/**
* 这个枚举用于指明是哪一种提交方式
*/
enum HttpMethodType {
GET,
POST
}
}
这里的BaseCallBack类:
public abstract class BaseCallback <T> {
public Type mType;
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]);
}
public BaseCallback()
{
mType = getSuperclassTypeParameter(getClass());
}
public abstract void onBeforeRequest(Request request);
public abstract void onFailure(Request request, Exception e) ;
/**
*请求成功时调用此方法
* @param response
*/
public abstract void onResponse(Response response);
/**
*
* 状态码大于200,小于300 时调用此方法
* @param response
* @param t
* @throws IOException
*/
public abstract void onSuccess(Response response,T t) ;
/**
* 状态码400,404,403,500等时调用此方法
* @param response
* @param code
* @param e
*/
public abstract void onError(Response response, int code,Exception e) ;
}
使用:
(1)创建单例实例
private OkHttpHelper httpHelper = OkHttpHelper.getInstance();
(2)直接调用get或者post方法
httpHelper.get(相应参数...)
httpHelper.post(相应参数..)