我们敲代码总是离不开网络请求。网络请求就是想服务器请求数据,一般请求到的数据就是我们列表上要展示数据的数据源。现在最长用的就是OkHttp、Volley、Retrofit2了。现在我们先说说OkHttp
想要使用OkHttp需要导入OkHttp的第三方依赖:
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
注意:如果你的Android Studio是3.0以下的版本要讲"implementation"改为"compile"。
导入依赖以后我们才能开始使用OkHttp。
1)我们需要创建OKHttpClient对象,OkHttpClient对象有2种方式创建:
1:通过new关键字直接创建
OkHttpClient okHttpClient =new OkHttpClient();
2:通过构建者模式创建OkHttpClient的内部类Builder对象来获取OKHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
我们常用第2种方法创建OkHttpClient对象。可以给OkHttpClient对象添加拦截器对象,而且构建者模式创建OkHttpClient对象代码看起来非常整洁。
添加拦截器对象:
添加应用拦截器对象addInterceptor(Interceptor interceptor),添加网络拦截器对象addNetworkInterceptor(Interceptor interceptor)这个拦截器对象稍后再说。
2)创建Request对象
这里我们不能直接通过new创建Request对象。因为Request的构造方法不是公共的,但是我们可以通过创建Request的内部类对象获取Request。
Request request =new Request.Builder().build();
在创建Request对象时可以配置url地址,请求方式、请求头
配置url地址:
Request request =new Request.Builder().url(String url).build();
配置其他方式一样在Builder()后直接打“.”调用就好了,我就直接贴方法了 。
设置请求方式:
1、get请求
get() //Request.Builder的方法
get请求可以不设置,默认就为get请求,你不需要再手动去设置请求方式。
2、post请求
post(RequestBody requestBody) //Request.Builder的方法
RequestBody该类是一个接口我们通常传入它的子类FormBody。
创建FormBody对象,和Request一样该类的构造方法不是公共的通过创建FormBody的内部类对象获取FormBody。
FormBody formBody =new FormBody.Builder().build();
post请求一般都有参数,如果post请求没有参数我们可以直接当做get请求来请求就OK了。那么post请求的参数在哪添加呢?在FormBody中添加通过add(String name,String value)添加参数信息。
添加请求头:
addHeader(String name,String value) //Request.Builder的方法
3)通过OkHttpClient对象发起请求
通过OkHttpClient的newCall(Requset request)方法返回Call对象。Call对象才是网络请求的真正执行者。
Call call =okHttpClient.newCall(request);
请求方式有2种:
1:同步请求
在发出同步请求后该线程会进入阻塞状态,等待请求完成在会继续往下执行。但是在Android中我们不能阻塞UI线程也就是主线程,如果主线程阻塞则程序直接挂掉。也就是我们常说的ANR异常。所有在用同步请求时要开一个子线程去请求数据。
Request request =new Request.Builder()
//设置url地址
.url(url).build();
//获取Call对象
Call call =okHttpClient.newCall(request);
try {
//发送同步请求
Response response = call.execute();
//将结果转为String
String responseStr = response.body().string();
}catch (IOException e) {
e.printStackTrace();
}
2:异步请求
在发出异步请求后OkHttp内部会开启一个线程去请求数据,数据请求完成之后会通过接口回调的方式来存储数据。主线程不会阻塞,但是以后相关的操作都要在数据回来的时候书写。
Request request =new Request.Builder()
//设置url地址
.url(url).build();
//获取Call对象
Call call =okHttpClient.newCall(request);
//发送异步请求
call.enqueue(new Callback() {
/*
在这个内部类的方法都是在子线程中,如果你需要更新UI的就要做线程之间的切换
*/
/**
* 请求失败的监听
* @param call
* @param e 失败的错误信息
*/
@Override
public void onFailure(Call call,final IOException e) {
//切换回主线程循环执行
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,"错误信息 : " +e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
/**
* 请求成功的监听
* @param call
* @param response 请求结果
* @throws IOException
*/
@Override
public void onResponse(Call call, Response response)throws IOException {
//获取请求体对象
ResponseBody responseBody = response.body();
//将请求结果转化为字符串
final String responseStr = responseBody.string();
/*
拿到数据之后,Gson解析数据
*/
//切换回主线程循环执行
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,"请求结果 : " +responseStr, Toast.LENGTH_SHORT).show();
}
});
}
});
到这里你就可以使用OkHttp来做一些简单的网络请求了。
下面说说给Okhttp配置拦截器:
有时候我们需要添加响应头信息、拦截响应头。在我们实际开发的过程中于后台联调也是通过拦截器来进行的。拦截器怎么重要,该怎么使用呢?
拦截器分两种
1.应用拦截器
addInterceptor(Interceptor interceptor) //OkHttpClient.Builder的方法
应用拦截器也叫日志拦截器。可以自己手动写应用拦截器,也可以导入依赖用Okhttp提供的应用拦截器
1).手动写拦截器
//创建拦截器对象
Interceptor interceptor =new Interceptor() {
@Override
public Response intercept(Chain chain)throws IOException {
//获取请求对象
Request request = chain.request();
//获取响应对象
Response response = chain.proceed(request);
//获取所有响应头
Headers headers = response.headers();
//便利所有响应头
Set names = headers.names();
for (String name : names) {
Log.d("OkHttpUtils", name +" : " + headers.get(name));
}
//一定要将原有响应对象返回,不要去new。否则请求不到数据
return response;
}
};
2).导入依赖实现拦截器
implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0'
//创建拦截器对象
HttpLoggingInterceptor interceptor =new HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT);
//设置打印信息 HEADERS为响应头 BODY为响应体 NONE为什么都不打印 BASIC为基本信息(响应头和响应体)
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
2.网络拦截器
addNetworkInterceptor(Interceptor interceptor) //OkHttpClient.Builder的方法
网络拦截器通常用于添加响应头,和拦截响应头时使用,比如设置缓存。网络拦截器只能手动书写,没有可导入的依赖。
Interceptor interceptor =new Interceptor() {
@Override
public Response intercept(Chain chain)throws IOException {
//获取请求对象
Request request = chain.request();
//获取响应对象
Response response = chain.proceed(request);
//通过原有的Response对象获取 Response.Builder
Response.Builder responseBuilder = response.newBuilder();
//添加响应头
Response newResponse = responseBuilder
.addHeader("key","value")
.addHeader("key2","value2").build();
//将新获取的Response对象返回
return newResponse;
}
};
最后说说设置缓存
我们做的网络请求,通常都会缓存数据。这样会给用户节约流量。
cache(Cache cache) //OkHttpClient.Builder的方法
缓存分两种情况:
1).后台服务器支持缓存
如果后台服务器支持缓存(响应头中有"Cache-Control"字段),直接设置存储地址与文件大小即可。
//创建Cache对象 App.context.getCacheDir()获取App的dir目录 文件大小
Cache cache =new Cache(App.context.getCacheDir(),1024 *1024 *10);
2).后台服务器不支持缓存
如果后台服务器不支持缓存(响应头中没有"Cache-Control"字段)。需要拦截响应头,手动添加"Cache-Control"字段,在设置存储地址与文件大小。
1.手动添加"Cache-Control"字段
Interceptorinterceptor =new Interceptor() {
@Override
public Response intercept(Chain chain)throws IOException {
//获取请求对象
Request request = chain.request();
//获取响应对象
Response response = chain.proceed(request);
//通过原有的Response对象获取 Response.Builder
Response.Builder responseBuilder = response.newBuilder();
//添加响应头
Response newResponse = responseBuilder
//添加Cache-Control字段支持缓存
.addHeader("Cache-Control","max-age=" +60 *60 *12)
.build();
//将新获取的Response对象返回
return newResponse;
}
};
2.设置存储地址与文件大小。
//创建Cache对象 App.context.getCacheDir()获取App的dir目录 文件大小
Cache cache =new Cache(App.context.getCacheDir(),1024 *1024 *10);
GetHub源码地址:https://github.com/AndroidHMH/OkHttpDemo