一.简介
在Android项目开发中使用HTTP协议完成与服务器通信的话,OkHttp是最常用的框架。OkHttp是一个高效的HTTP客户端,是目前Android使用最广泛的网络框架。它有几个优点。
<1> 支持Http1、Http2、Quic以及WebSocket。
<2> 连接池复用底层TCP(Socket) 减少请求延时。
<3> 无缝的支持GZIP减少数据流量。
<4> 缓存响应数据减少重复的网络请求。
<5> 请求失败自动重试主机的其他ip,自动重定向。
二.代码实现
1.Gradle依赖
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
2.Get&Post请求
package com.wjn.networkdemo.okhttp.only;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.wjn.networkdemo.R;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class OkHttpOnlyActivity extends AppCompatActivity {
private TextView textView1;
private TextView textView2;
private String getUrl = "http://fanyi.youdao.com/openapi.do?keyfrom=imoocdict123456&key=324273592&type=data&doctype=json&version=1.1&q=blue";
private String postUrl = "http://fanyi.youdao.com/openapi.do";
private OkHttpClient mOkHttpClient = null;//OkHttpClient 对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_okhttp_only);
textView1 = findViewById(R.id.activity_okhttp_only_textview1);
textView2 = findViewById(R.id.activity_okhttp_only_textview2);
//创建OkHttpClient对象
mOkHttpClient = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)//连接时间
.readTimeout(20, TimeUnit.SECONDS)//读时间
.writeTimeout(20, TimeUnit.SECONDS)//写时间
.retryOnConnectionFailure(true)//连接失败后是否重新连接
.build();
textView1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getData();
}
});
textView2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Map<String, String> params = new HashMap<>();
params.put("keyfrom", "imoocdict123456");
params.put("key", "324273592");
params.put("type", "data");
params.put("doctype", "json");
params.put("version", "1.1");
params.put("q", "red");
postData(params);
}
});
}
/**
* OkHttp Get请求
*/
private void getData() {
//1.创建Request对象 构建一个具体的网络请求对象 包括具体的请求url&请求头&请求体等等
Request request = new Request.Builder().url(getUrl).get().build();
//2.获取Call对象 将具体的网络请求与执行请求的实体进行绑定,形成一个具体的正式的可执行实体
Call call = mOkHttpClient.newCall(request);
//3.Call对象进行网络请求 enqueue异步 execute同步一般不用
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("OkHttpOnlyActivity", "Get请求 onFailure方法执行 错误信息----:" + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (null != response && response.isSuccessful()) {
Log.d("OkHttpOnlyActivity", "Get请求 onResponse方法执行报文----:" + response.body().string());
}
}
});
}
/**
* OkHttp Post请求
*/
private void postData(final Map<String, String> params) {
//1.获取FormBody.Builder对象
FormBody.Builder builder = new FormBody.Builder();
//2.遍历params 将其放入到FormBody.Builder 对象
if (params != null && !params.isEmpty()) {
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.add(entry.getKey(), entry.getValue());
}
}
//3.获取RequestBody 对象
RequestBody requestBody = builder.build();
//4.创建Request对象 构建一个具体的网络请求对象 包括具体的请求url&请求头&请求体等等
Request request = new Request.Builder().url(postUrl).post(requestBody).build();
//5.获取Call对象 将具体的网络请求与执行请求的实体进行绑定,形成一个具体的正式的可执行实体
Call call = mOkHttpClient.newCall(request);
//6.Call对象进行网络请求 enqueue异步 execute同步一般不用
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("OkHttpOnlyActivity", "Post请求 onFailure方法执行 错误信息----:" + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (null != response && response.isSuccessful()) {
Log.d("OkHttpOnlyActivity", "Post请求 onResponse方法执行报文----:" + response.body().string());
}
}
});
}
}
3.结果
<1> Get请求
D/OkHttpOnlyActivity: Get请求 onResponse方法执行报文----:{"translation":["蓝色的"],"basic":{"us-phonetic":"bluː","phonetic":"bluː","uk-phonetic":"bluː","explains":["adj. 蓝色的;忧郁的,悲观的;(由于冷或呼吸困难)发青的,青紫的;(电影、玩笑或故事)色情的,黄色的;(肉)未熟的;(政治上)保守的","n. 蓝色;蓝色物品;(牛津或剑桥大学的运动员)蓝色荣誉者;失误;红发人;打架","vt. (使)变成蓝色;把......染成蓝色;给\u2026\u2026上蓝色漂白剂;挥霍(钱财)","n. (Blue) (英、美、加、澳、新)布卢(人名)"]},"query":"blue","errorCode":0,"web":[{"value":["蓝色的","刀枪不入","蓝色橙味糖浆"],"key":"blue"},{"value":["蓝月","蓝月亮","千载难逢的时机"],"key":"Blue Moon"},{"value":["青尼罗省","青尼罗河","蓝色尼罗河"],"key":"Blue Nile"}]}
<2> Post请求
D/OkHttpOnlyActivity: Post请求 onResponse方法执行报文----:{"translation":["红色的"],"basic":{"us-phonetic":"red","phonetic":"red","uk-phonetic":"red","explains":["adj. 红的,红色的;(毛发)红褐色的;(脸)涨红的;(眼睛)红肿的;革命的,激进的;(人)红种的;(纸牌中)红桃的,红方块的;(葡萄酒)红的;(表示停止)红(灯),红(旗);被禁止的,危险的;(滑雪道上用红色标志指示)第二高难度的;(物理)表示夸克三种颜色之一的红色;赤色的(尤指冷战期间用于指前苏联);沾有鲜血的;(古或诗\/文)流血的;(科萨人)来自传统部落文化的","n. 红色,红颜料;红衣;红葡萄酒;红色物(或人);赤字,亏空;激进分子","n. (Red) 雷德(人名)"]},"query":"red","errorCode":0,"web":[{"value":["红","红色","赤焰战场"],"key":"RED"},{"value":["红线","台北捷运红线","红线机油"],"key":"Red Line"},{"value":["红旗","红旗演习","危险信号"],"key":"red flag"}]}
4.补充
<1> OKHTTP请求成功之后在onResponse方法中可以得到一个Response对象。
[1] 如果想获得返回的字符串结果则可以通过response.body().string()。
[2] 如果想获得返回结果的二进制数据的话可以通过response.body().bytes()。
[3] 如果想获得返回的InputStream的话可以通过response.body().byteStream()。
且拿各种返回报文时,需要判断Response对象是否为空且是否成功。代码如上。
<2> OkHttp的主角们
[1] OkHttpClient
Factory for calls, which can be used to send HTTP requests and read their responses.
工厂生产者,负责生产calls。
OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
.connectTimeout(DataConstant.nettimeout, TimeUnit.SECONDS)//连接时间
.readTimeout(DataConstant.nettimeout, TimeUnit.SECONDS)//读时间
.writeTimeout(DataConstant.nettimeout, TimeUnit.SECONDS)//写时间
.build();
[2] Request
OkHttp的请求,通过Request.Builder().build
创建, Request.Builder()
配置请求信息,如请求方式get/post
等、请求参数RequestBody
、请求头header
。
Request request = new Request.Builder().addHeader("cookie", cookie).url(url).get().build();
[3] Call
调度者,Call作顶级接口,具体实现由RealCall负责。负责Request
和Response
的桥梁作用,将Request
以execute()
同步的方式执行输出Response
, 或将Request
以enqueue(callback)
异步的方式加入调度。
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
<3> OKHttp框架GitHub链接:https://github.com/square/okhttp