拦截器是一个监视、重写、重试请求的强有力机制。
搭建环境
1.搭建环境(依赖,权限)(okhttp的依赖即可)
2.完成布局,初始化控件
3.写拦截器
-----a.原生拦截器
----------1.日志拦截器
----------2.压缩拦截器
-----b.自定义拦截器,封装公共参数
拦截器博客(简单版-个人编写)
https://blog.youkuaiyun.com/L_1145418863/article/details/84316503
添加依赖和网络权限
compile ‘com.squareup.okhttp3:okhttp:3.4.2’
uses-permission android:name=“android.permission.INTERNET”
写布局文件 (也仅仅是为了测试网络封装是否可用)
<Button
android:onClick="okhttp_json"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取Json数据(GET)"/>
<Button
android:onClick="okhttp_table"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="表单提交(POST)"/>
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!--ScrollView只能包裹一个直接的子view,否则会报错,解决办法就是放一个容器,然后容器里面有多少控件就没有关系了-->
<TextView
android:id="@+id/text_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
</ScrollView>
写完布局文件 MainActivity中的代码暂时不写,等网络拦截器写完后再写
写一个类实现拦截器的接口Interceptor
//自定义一个拦截器,封装公共请求参数
public class PublicParamInterceptor implements Interceptor {
//初始化Map对象
Map<String, String> paramMap;
public PublicParamInterceptor(Map<String, String> paramMap) {
this.paramMap = paramMap;
}
@Override
public Response intercept(Chain chain) throws IOException {
//拿到原来的request
Request oldRequest = chain.request();
//拿到请求的url
String url = oldRequest.url().toString();
//判断是GET还是POST请求
if (oldRequest.method().equalsIgnoreCase("GET")) {
if (paramMap != null && paramMap.size() > 0) {
StringBuilder urlBuilder = new StringBuilder(url);
//拼接公共请求参数
for (Map.Entry<String, String> entry : paramMap.entrySet()) {
urlBuilder.append("&" + entry.getKey() + "=" + entry.getValue());
}
url = urlBuilder.toString();
//如果之前的url没有?号,我们需要手动给他添加一个?号
if (!url.contains("?")) {
url = url.replaceFirst("&", "?");
}
//依据原来的request构造一个新的request,
Request request = oldRequest.newBuilder()
.url(url)
.build();
return chain.proceed(request);
}
} else {
if (paramMap != null && paramMap.size() > 0) {
RequestBody body = oldRequest.body();
if (body != null && body instanceof FormBody) {
FormBody formBody = (FormBody) body;
//1.把原来的的body里面的参数添加到新的body中
FormBody.Builder builder = new FormBody.Builder();
//为了防止重复添加相同的key和value
Map<String, String> temMap = new HashMap<>();
for (int i = 0; i < formBody.size(); i++) {
builder.add(formBody.encodedName(i), formBody.encodedValue(i));
temMap.put(formBody.encodedName(i), formBody.encodedValue(i));
}
//2.把公共请求参数添加到新的body中
for (Map.Entry<String, String> entry : paramMap.entrySet()) {
if(!temMap.containsKey(entry.getKey())){
builder.add(entry.getKey(), entry.getValue());
}
}
FormBody newFormBody = builder.build();
//依据原来的request构造一个新的request,
Request newRequest = oldRequest.newBuilder()
.post(newFormBody)
.build();
return chain.proceed(newRequest);
}
}
}
return chain.proceed(oldRequest);
}
}
写完网络拦截器 写网络请求的类
(实现拦截器的使用)
public class OkhtttpUtils {
////////////////////////////////////////////////单例//////////////////////////////////////
private static OkhtttpUtils mOkhtttpUtils;
private OkHttpClient mOkHttpClien;
private final Handler mHandler;
//构造方法私有
private OkhtttpUtils() {
//B.okhttp添加公共参数到拦截器中
Map<String, String> map = new HashMap<>();
map.put("source", "android");
PublicParamInterceptor publicParamInterceptor = new PublicParamInterceptor(map);
//创建一个主线程的handler
mHandler = new Handler(Looper.getMainLooper());
mOkHttpClien = new OkHttpClient.Builder()
.connectTimeout(5000, TimeUnit.MILLISECONDS)
.readTimeout(5000, TimeUnit.MILLISECONDS)
.writeTimeout(5000, TimeUnit.MILLISECONDS)
//B.添加okhttp的拦截器
.addInterceptor(publicParamInterceptor)
.build();
}
//单例模式
public static OkhtttpUtils getInstance() {
if (mOkhtttpUtils == null) {
synchronized (OkhtttpUtils.class) {
if (mOkhtttpUtils == null) {
return mOkhtttpUtils = new OkhtttpUtils();
}
}
}
return mOkhtttpUtils;
}
//////////////////////////////////////////////////////接口////////////////////////////////
public interface OkCallback {
void onFailure(Exception e);
void onResponse(String json);
}
////////////////////////////////////////////okhttp与handler///////////////////////////
//封装doGEt的网络封装,参数定义两个,一个是URL网址 一个实现接口的对象
public void doGet(String url, final OkCallback ycfOkhttpCallback) {
//创建FormBody对象,把表单添加到FormBody
Request request = new Request.Builder()
.get()
.url(url)
.build();
final Call call = mOkHttpClien.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
if (ycfOkhttpCallback != null) {
//切换到主线程
mHandler.post(new Runnable() {
@Override
public void run() {
ycfOkhttpCallback.onFailure(e);
}
});
}
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (response != null && response.isSuccessful()) {
final String json = response.body().string();
if (ycfOkhttpCallback != null) {
//切换到主线程
mHandler.post(new Runnable() {
@Override
public void run() {
ycfOkhttpCallback.onResponse(json);
}
});
}
}
}
});
}
//封装doPost的逻辑代码
public void doPost(String url, Map<String, String> map, final OkCallback ycfOkCallback) {
//创建FormBody的对象,把表单添加到formBody中
FormBody.Builder builder = new FormBody.Builder();
//集合对象不为null的情况下
if (map != null) {
for (String key : map.keySet()) {
builder.add(key, map.get(key));
}
}
FormBody formBody = builder.build();
//创建Request对象
Request request = new Request.Builder()
.post(formBody)
.url(url)
.build();
//创建Call对象
final Call call = mOkHttpClien.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
if (ycfOkCallback != null) {
//切换到主线程
mHandler.post(new Runnable() {
@Override
public void run() {
ycfOkCallback.onFailure(e);
}
});
}
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (response != null && response.isSuccessful()) {
final String json = response.body().string();
if (ycfOkCallback != null) {
//切换到主线程
mHandler.post(new Runnable() {
@Override
public void run() {
ycfOkCallback.onResponse(json);
}
});
}
}
else if (ycfOkCallback != null) {
ycfOkCallback.onFailure(new Exception("服务器异常"));
}
}
});
}
}
最后写MainActivity中的代码
public class MainActivity extends AppCompatActivity {
//GET接口网址
// private String json_path = "http://publicobject.com/helloworld.txt";
//post
private String json_path = "http://gank.io/api/data/%E7%A6%8F%E5%88%A9/10/1";
//Post请求接口网址 bw购物车的内容 共有字段"source", "android"添加到拦截器中 参数"uid","71"
String url = "http://www.zhaoapi.cn/product/getCarts";
private TextView text_tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text_tv = (TextView) findViewById(R.id.text_tv);
}
/**
* 通过点击事件执行okhttp里封装的根据网址,获取字符串的逻辑操作.
* @param view
*
*/
public void okhttp_json(View view){
OkhtttpUtils.getInstance().doGet(json_path, new OkhtttpUtils.OkCallback() {
@Override
public void onFailure(Exception e) {
Toast.makeText(MainActivity.this, "网络请求失败", Toast.LENGTH_SHORT).show();
}
@Override
public void onResponse(String json) {
text_tv.setText(json);
}
});
}
//像服务器提交账号及密码
public void okhttp_table(View view){
HashMap<String, String> map = new HashMap<>();
map.put("uid","71");
OkhtttpUtils.getInstance().doPost(url, map, new OkhtttpUtils.OkCallback() {
@Override
public void onFailure(Exception e) {
Toast.makeText(MainActivity.this, "网络请求失败", Toast.LENGTH_SHORT).show();
}
@Override
public void onResponse(String json) {
text_tv.setText(json);
}
});
}
}
最后附上一个网络请求框架 比我的强得多~[汗颜]
一个http请求的封装框架
https://github.com/angcyo/OkHttpUtils/blob/master/README.md