您的位置:首页 > 理论基础 > 计算机网络

Android okhttp3的基本使用

2016-07-02 12:16 369 查看

okhttp3的基本使用

一 导入okhttp3.3.1

compile 'com.squareup.okhttp3:okhttp:3.3.1'
compile 'com.squareup.okio:okio:1.8.0'


这里提醒一下本人在不导入com.squareup.okio:okio:1.8.0时连接服务器时失败——

二 基本使用

1、okhttp3 Get 方法

1.1 、okhttp3 同步 Get方法

//同步get方式提交
private void getRequest() {
new Thread(new Runnable() {
@Override
public void run() {
try {
String url = "http://apicloud.mob.com/v1/weather/query?key=146d30f8f3b93&city=长沙&province=湖南";
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String string = response.body().string();
Gson gson = new Gson();
Root root = gson.fromJson(response.body().charStream(),Root.class);
Log.i("wxy",root.getRetCode());
Message mag = handler.obtainMessage();
mag.obj = string;
handler.sendMessage(mag);
} else {
Log.i("wxy", "okHttp is request error");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}


1.2 、okhttp3 异步 Get方法

有时候需要下载一份文件(比如网络图片),如果文件比较大,整个下载会比较耗时,通常我们会将耗时任务放到工作线程中,而使用okhttp3异步方法,不需要我们开启工作线程执行网络请求,返回的结果也在工作线程中;

private void okHttp_asynchronousGet(){
try {
Log.i("wxy","main thread id is "+Thread.currentThread().getId());
String url = "http://apicloud.mob.com/v1/weather/query?key=146d30f8f3b93&city=长沙&province=湖南";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {

}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
// 注:该回调是子线程,非主线程
Log.i("wxy","callback thread id is "+Thread.currentThread().getId());
Log.i("wxy",response.body().string());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}


2 、okhttp3 同步 Get方法

很多时候,我们需要通过Post方式把键值对数据传送到服务器,okhttp3使用FormBody.Builder创建请求的参数键值对;

private void okHttp_postFromParameters() {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 请求完整url:http://api.k780.com:88/?app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json
String url = "http://api.k780.com:88/";
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody formBody = new FormBody.Builder().add("app", "weather.Future")
.add("weaid", "1").add("appkey", "10003").add("sign",
"b59bc3ef6191eb9f747dd4e83c99f2a4").add("format", "json")
.build();
Request request = new Request.Builder().url(url).post(formBody).build();
okhttp3.Response response = okHttpClient.newCall(request).execute();
Log.i("wxy", response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}


请求缓存

在网络请求中,缓存技术是一项应用比较广泛的技术,需要对请求过的网络资源进行缓存,而okhttp也支持这一技术,也使用十分方便,前文涨经常出现的OkHttpclient这个时候就要派送用场了。看下面代码

package com.jackchan.test.okhttptest;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;

import com.squareup.okhttp.Cache;
import com.squareup.okhttp.CacheControl;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.IOException;

public class TestActivity extends ActionBarActivity {

private final static String TAG = "TestActivity";

private final OkHttpClient client = new OkHttpClient();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
File sdcache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024; // 10 MiB
client.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
new Thread(new Runnable() {
@Override
public void run() {
try {
execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}

public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();

Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);

String response1Body = response1.body().string();
System.out.println("Response 1 response:          " + response1);
System.out.println("Response 1 cache response:    " + response1.cacheResponse());
System.out.println("Response 1 network response:  " + response1.networkResponse());

Response response2 = client.newCall(request).execute();
if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);

String response2Body = response2.body().string();
System.out.println("Response 2 response:          " + response2);
System.out.println("Response 2 cache response:    " + response2.cacheResponse());
System.out.println("Response 2 network response:  " + response2.networkResponse());

System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));

}
}


okhttpclient有点像Application的概念,统筹着整个okhttp的大功能,通过它设置缓存目录,我们执行上面的代码,得到的结果如下


response1 的结果在networkresponse,代表是从网络请求加载过来的,而response2的networkresponse 就为null,而cacheresponse有数据,因为我设置了缓存因此第二次请求时发现缓存里有就不再去走网络请求了。

但有时候即使在有缓存的情况下我们依然需要去后台请求最新的资源(比如资源更新了)这个时候可以使用强制走网络来要求必须请求网络数据。

public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();

Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);

String response1Body = response1.body().string();
System.out.println("Response 1 response:          " + response1);
System.out.println("Response 1 cache response:    " + response1.cacheResponse());
System.out.println("Response 1 network response:  " + response1.networkResponse());

request = request.newBuilder().cacheControl(CacheControl.FORCE_NETWORK).build();
Response response2 = client.newCall(request).execute();
if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);

String response2Body = response2.body().string();
System.out.println("Response 2 response:          " + response2);
System.out.println("Response 2 cache response:    " + response2.cacheResponse());
System.out.println("Response 2 network response:  " + response2.networkResponse());

System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));

}


上面的代码中

response2对应的request变成

request = request.newBuilder().cacheControl(CacheControl.FORCE_NETWORK).build();


我们看看运行结果



response2的cache response为null,network response依然有数据。

同样的我们可以使用 FORCE_CACHE 强制只要使用缓存的数据,但如果请求必须从网络获取才有数据,但又使用了FORCE_CACHE 策略就会返回504错误,代码如下,我们去okhttpclient的缓存,并设置request为FORCE_CACHE

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
File sdcache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024; // 10 MiB
//client.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
new Thread(new Runnable() {
@Override
public void run() {
try {
execute();
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage().toString());
}
}
}).start();
}

public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();

Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);

String response1Body = response1.body().string();
System.out.println("Response 1 response:          " + response1);
System.out.println("Response 1 cache response:    " + response1.cacheResponse());
System.out.println("Response 1 network response:  " + response1.networkResponse());

request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
Response response2 = client.newCall(request).execute();
if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);

String response2Body = response2.body().string();
System.out.println("Response 2 response:          " + response2);
System.out.println("Response 2 cache response:    " + response2.cacheResponse());
System.out.println("Response 2 network response:  " + response2.networkResponse());

System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));

}




取消操作

网络操作中,经常会使用到对请求的cancel操作,okhttp的也提供了这方面的接口,call的cancel操作。使用Call.cancel()可以立即停止掉一个正在执行的call。如果一个线程正在写请求或者读响应,将会引发IOException,同时可以通过Request.Builder.tag(Object tag)给请求设置一个标签,并使用OkHttpClient.cancel(Object tag)来取消所有带有这个tag的call。但如果该请求已经在做读写操作的时候,cancel是无法成功的,会抛出IOException异常。

public void canceltest() throws Exception {
Request request = new Request.Builder()
.url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
.build();

final long startNanos = System.nanoTime();
final Call call = client.newCall(request);

// Schedule a job to cancel the call in 1 second.
executor.schedule(new Runnable() {
@Override
public void run() {
System.out.printf("%.2f Canceling call.%n", (System.nanoTime() - startNanos) / 1e9f);
call.cancel();
System.out.printf("%.2f Canceled call.%n", (System.nanoTime() - startNanos) / 1e9f);
}
}, 1, TimeUnit.SECONDS);

try {
System.out.printf("%.2f Executing call.%n", (System.nanoTime() - startNanos) / 1e9f);
Response response = call.execute();
System.out.printf("call is cancel:" + call.isCanceled() + "%n");
System.out.printf("%.2f Call was expected to fail, but completed: %s%n",
(System.nanoTime() - startNanos) / 1e9f, response);
} catch (IOException e) {
System.out.printf("%.2f Call failed as expected: %s%n",
(System.nanoTime() - startNanos) / 1e9f, e);
}
}


成功取消



取消失败



简单的对于OKHttp的使用就介绍到这里,下次将重点从源码角度介绍整个OKHttp是如何运转的。

这是我自己写的简单的测试代码——解析线上的天气JSON

package com.test.okhttp;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.google.gson.Gson;
import java.io.IOException;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {
private Button btn_get;
private Button btn_post;
OkHttpClient client = new OkHttpClient();
//本地testJson数据
String json= "JSON数据";

//JSON数据不可再子线程中转换输出,要在主线程中转换输出。
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String jsonString = (String) msg.obj;
Gson gson = new Gson();
Root fromJson = gson.fromJson(jsonString,Root.class);
Log.i("wxy",fromJson.getRetCode());
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_get = (Button) findViewById(R.id.btn_get);
btn_get.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getRequest();
}
});
btn_post = (Button) findViewById(R.id.btn_post);
}
private void testJson(){
Gson gson = new Gson();
Root fromJson = gson.fromJson(json,Root.class);
Log.i("wxy",fromJson.getMsg());
}
//同步get方式提交
private void getRequest() {
new Thread(new Runnable() {
@Override
public void run() {
try {
String url = "http://apicloud.mob.com/v1/weather/query?key=146d30f8f3b93&city=长沙&province=湖南";
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String string = response.body().string();
Message mag = handler.obtainMessage();
mag.obj = string;
handler.sendMessage(mag);
} else {
Log.i("wxy", "okHttp is request error");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 异步 Get方法
*/
private void okHttp_asynchronousGet(){ try { Log.i("wxy","main thread id is "+Thread.currentThread().getId()); String url = "http://apicloud.mob.com/v1/weather/query?key=146d30f8f3b93&city=长沙&province=湖南"; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(url).build(); client.newCall(request).enqueue(new okhttp3.Callback() { @Override public void onFailure(okhttp3.Call call, IOException e) { } @Override public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException { // 注:该回调是子线程,非主线程 Log.i("wxy","callback thread id is "+Thread.currentThread().getId()); Log.i("wxy",response.body().string()); } }); } catch (Exception e) { e.printStackTrace(); } }

/**
* Post 提交键值对
* 如果是异步同get方式异步提交一致
*/
private void okHttp_postFromParameters() { new Thread(new Runnable() { @Override public void run() { try { // 请求完整url:http://api.k780.com:88/?app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json String url = "http://api.k780.com:88/"; OkHttpClient okHttpClient = new OkHttpClient(); RequestBody formBody = new FormBody.Builder().add("app", "weather.Future") .add("weaid", "1").add("appkey", "10003").add("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4").add("format", "json") .build(); Request request = new Request.Builder().url(url).post(formBody).build(); okhttp3.Response response = okHttpClient.newCall(request).execute(); Log.i("wxy", response.body().string()); } catch (Exception e) { e.printStackTrace(); } } }).start(); }

}


下面及时天气的数据实体

Root.java

package com.test.okhttp;

/**
* Created by WXY on 2016/6/30.
*/
import java.io.Serializable;
import java.util.List;

public class Root implements Serializable{
private String msg;

private List<Result> result ;

private String retCode;

public void setMsg(String msg){
this.msg = msg;
}
public String getMsg(){
return this.msg;
}
public void setResult(List<Result> result){
this.result = result;
}
public List<Result> getResult(){
return this.result;
}
public void setRetCode(String retCode){
this.retCode = retCode;
}
public String getRetCode(){
return this.retCode;
}
}


Future.java

package com.test.okhttp;

import java.io.Serializable;

/**
* Created by WXY on 2016/6/30.
*/

public class Future implements Serializable{
private String date;

private String dayTime;

private String night;

private String temperature;

private String week;

private String wind;

public void setDate(String date){
this.date = date;
}
public String getDate(){
return this.date;
}
public void setDayTime(String dayTime){
this.dayTime = dayTime;
}
public String getDayTime(){
return this.dayTime;
}
public void setNight(String night){
this.night = night;
}
public String getNight(){
return this.night;
}
public void setTemperature(String temperature){
this.temperature = temperature;
}
public String getTemperature(){
return this.temperature;
}
public void setWeek(String week){
this.week = week;
}
public String getWeek(){
return this.week;
}
public void setWind(String wind){
this.wind = wind;
}
public String getWind(){
return this.wind;
}
}


Result.java

package com.test.okhttp;

import java.io.Serializable;
import java.util.List;

/**
* Created by WXY on 2016/6/30.
*/

public class Result  implements Serializable{
private String airCondition;

private String city;

private String coldIndex;

private String date;

private String distrct;

private String dressingIndex;

private String exerciseIndex;

private List<Future> future ;

private String humidity;

private String pollutionIndex;

private String province;

private String sunrise;

private String sunset;

private String temperature;

private String time;

private String updateTime;

private String washIndex;

private String weather;

private String week;

private String wind;

public void setAirCondition(String airCondition){
this.airCondition = airCondition;
}
public String getAirCondition(){
return this.airCondition;
}
public void setCity(String city){
this.city = city;
}
public String getCity(){
return this.city;
}
public void setColdIndex(String coldIndex){
this.coldIndex = coldIndex;
}
public String getColdIndex(){
return this.coldIndex;
}
public void setDate(String date){
this.date = date;
}
public String getDate(){
return this.date;
}
public void setDistrct(String distrct){
this.distrct = distrct;
}
public String getDistrct(){
return this.distrct;
}
public void setDressingIndex(String dressingIndex){
this.dressingIndex = dressingIndex;
}
public String getDressingIndex(){
return this.dressingIndex;
}
public void setExerciseIndex(String exerciseIndex){
this.exerciseIndex = exerciseIndex;
}
public String getExerciseIndex(){
return this.exerciseIndex;
}
public void setFuture(List<Future> future){
this.future = future;
}
public List<Future> getFuture(){
return this.future;
}
public void setHumidity(String humidity){
this.humidity = humidity;
}
public String getHumidity(){
return this.humidity;
}
public void setPollutionIndex(String pollutionIndex){
this.pollutionIndex = pollutionIndex;
}
public String getPollutionIndex(){
return this.pollutionIndex;
}
public void setProvince(String province){
this.province = province;
}
public String getProvince(){
return this.province;
}
public void setSunrise(String sunrise){
this.sunrise = sunrise;
}
public String getSunrise(){
return this.sunrise;
}
public void setSunset(String sunset){
this.sunset = sunset;
}
public String getSunset(){
return this.sunset;
}
public void setTemperature(String temperature){
this.temperature = temperature;
}
public String getTemperature(){
return this.temperature;
}
public void setTime(String time){
this.time = time;
}
public String getTime(){
return this.time;
}
public void setUpdateTime(String updateTime){
this.updateTime = updateTime;
}
public String getUpdateTime(){
return this.updateTime;
}
public void setWashIndex(String washIndex){
this.washIndex = washIndex;
}
public String getWashIndex(){
return this.washIndex;
}
public void setWeather(String weather){
this.weather = weather;
}
public String getWeather(){
return this.weather;
}
public void setWeek(String week){
this.week = week;
}
public String getWeek(){
return this.week;
}
public void setWind(String wind){
this.wind = wind;
}
public String getWind(){
return this.wind;
}
}


三、参考文献:

http://blog.csdn.net/chenzujie/article/details/46994073

http://blog.csdn.net/peak1chen/article/details/51564494
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 第三方