OkHttp是一个关于网络请求的第三方类库,其中封装了网络请求的get、post等操作的底层实现,是Android端目前最为火热的网络请求框架之一。
在Android Studio中不需要下载专门的jar包,直接在gradle中添加依赖,如下所示:
compile 'com.squareup.okhttp3:okhttp:3.10.0' 复制代码
new Thread(new Runnable() { @Override public void run() { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url("http:www.taobao.com").build(); try { Response response = client.newCall(request).execute(); if (response.isSuccessful()) { Log.d("ABC", "response=" + response.body().toString()); // 转到UI线程去修改UI } } catch (IOException e) { e.printStackTrace(); } } }).start(); 复制代码
get同步请求分为三步: 首先使用new创建OkHttpClient对象。 然后调用OkHttpClient对象的newCall方法生成一个Call对象,该方法接收一个Request对象,Request对象存储的就是我们的请求URL和请求参数。 最后执行Call对象的execute方法,得到Response对象,这个Response对象就是返回的结果。
OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url("http://www.tabao.com").build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.d("ABC", "error"); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { Log.d("ABC", "response=" + response.body().toString()); // 转到UI线程去修改UI } } }); 复制代码
get异步请求分为三步: 首先使用new创建OkHttpClient对象。 然后调用OkHttpClient对象的newCall方法生成一个Call对象,该方法接收一个Request对象,Request对象存储的是我们的请求URL和请求参数。 最后执行Call对象的enqueue方法,该方法接收一个Callback回调对象,在回调对象的onResponse方法中拿到Response对象,这就是返回的结果。
总结:get的同步方法和异步方法的差别在于同步方法需要手动开启一个线程执行,而异步方法不需要(其实是使用了内部的线程)。
new Thread(new Runnable() { @Override public void run() { OkHttpClient client = new OkHttpClient(); FormBody.Builder formBody = new FormBody.Builder(); formBody.add("bookName", "Android Art"); Request request = new Request.Builder().url("http:www.taobao.com").post(formBody.build()).build(); try { Response response = client.newCall(request).execute(); if (response.isSuccessful()) { Log.d("ABC", "response=" + response.body().toString()); // 转到UI线程去修改UI } } catch (IOException e) { e.printStackTrace(); } } }).start(); 复制代码
对比:post方法的同步请求和get方法的同步请求的区别在于,post方法生成Request对象时多执行了post(RequestBody)方法,而RequestBody对象的子类是FormBody类,所以可以使用FormBody对象创建键值对参数。
再深入一步,为什么post请求需要执行post方法,而且get请求不用呢?我们看一下post方法里面执行了什么操作?
public Builder post(RequestBody body) { return method("POST", body); } 复制代码
返回了method方法的执行结果,这里传递了一个“POST”字符串,看一下method方法的执行:
public Builder method(String method, RequestBody body) { if (method == null) throw new NullPointerException("method == null"); if (method.length() == 0) throw new IllegalArgumentException("method.length() == 0"); if (body != null && !HttpMethod.permitsRequestBody(method)) { throw new IllegalArgumentException("method " + method + " must not have a request body."); } if (body == null && HttpMethod.requiresRequestBody(method)) { throw new IllegalArgumentException("method " + method + " must have a request body."); } this.method = method; this.body = body; return this; } 复制代码
这里将“POST"字符串传递给了Builder对象的method变量,而Builder的默认构造函数中将method变量赋值为"GET"。到这里就水落石出了,原来Request.Builder对象创建时,默认就是get请求,所以get请求就不用设置get方法了,而post请求则需要修改method变量的值为"POST"。
OkHttpClient client = new OkHttpClient(); FormBody.Builder formBody = new FormBody.Builder(); formBody.add("bookName", "Android Art"); Request request = new Request.Builder().url("http://www.tabao.com").post(formBody.build()).build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.d("ABC", "error"); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { Log.d("ABC", "response=" + response.body().toString()); // 转到UI线程去修改UI } } }); 复制代码
Retrofit是一个RESTful的HTTP网络请求框架,它是基于OkHttp的。它是通过注解配置网络参数的,支持多种数据的解析和序列化(Gson、Json、Xml等,并且对RxJava也是支持的。下面是Retrofit和OkHttp的联系图(图来自于https://blog.csdn.net/carson_ho/article/details/73732076):
可以看到App应用层是通过Retrofit请求网络,然后使用Retrofit接口层封装请求参数、Header、URL等信息,然后由OkHttp完成后续的和服务器的交互。 而服务器返回响应数据后,也是先返回给OkHttp,然后OkHttp将原始结果返回给Retrofit,Retrofit根据用户的需求对原始数据进行解析封装,并返回给App应用层。
在Android Studio中Retrofit库的依赖,由于其还依赖了OkHttp库,所以同时需要添加OkHttp的依赖。
compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.okhttp3:okhttp:3.8.1' 复制代码
Retrofit使用 注解 的方式描述和配置网络请求参数。实际上是运用动态代理的方式将注解翻译成一个Http请求,然后执行该请求。基本的结构如下:
public interface GitHubService { @GET("getUserData") Call<User> getCall(); } 复制代码
User.java
public class User { private int userId; private String userName; private ExInfo exInfo; private static class ExInfo { private String from; private String birthDay; } public void show() { Log.d("ABC", "userId=" + userId); Log.d("ABC", "userName=" + userName); Log.d("ABC", "from=" + exInfo.from); Log.d("ABC", "birthday=" + exInfo.birthDay); } } 复制代码
注意项: 1、这是一个接口(Interface)不是一个类(class)。 2、其中可以创建不同的接口方法。 3、每一个接口方法和接口方法的参数必须使用注解的方式标注,否则会报错。 4、请求方法有GET、POST、PUT、HEAD、DELETE等。 5、方法的返回类型必须为Call,xxx是接收数据的类(可以是我们自定义的类,也可以是ResponseBody)。 6、User中字段的名字必须和后台Json定义的字段名是一致的,这样Json才能解析成功。
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://10.75.114.138:8081/") .addConverterFactory(GsonConverterFactory.create()).build(); //设置网络请求的Url地址 .addConverterFactory(GsonConverterFactory.create()) //设置数据解析器 .build(); 复制代码
网络请求的地址:创建Retrofit对象时通过baseUrl()设置+网络请求接口的注解设置。 addConverterFactory(GsonConverterFactory.create())的作用是设置数据解析器,它可以解析Gson、JsonObject、JsonArray这三种格式的数据。
// 创建 网络请求接口 的实例 GitHubServiceRequest request = retrofit.create(GitHubService.class); //对 发送请求 进行封装 Call<Reception> call = request.getCall(); 复制代码
同步请求:
// 发送网络请求(同步) Response<Reception> response = call.execute(); 复制代码
异步请求:
call.enqueue(new Callback<User>() { //请求成功后回调 @Override public void onResponse(Call<User> call, Response<User> response) { //处理请求结果 User user = response.body(); if(user != null) { user.show(); } } //请求失败后回调 @Override public void onFailure(Call<User> call, Throwable throwable) { System.out.println("请求失败"); } }); 复制代码
Retrofit的一个RESTful风格的网络请求框架,其下一层的实现也是OkHttp,所以其原理和OkHttp的一样的,只是在OkHttp的上面封装了一层,使请求接口和数据解析更加简洁明了。