安卓网络RxJavaAndroid专题

RxJava<第三十一篇>:Android开发必须了

2019-04-05  本文已影响19人  NoBugException
(1)依赖
//OKHttp依赖
implementation 'com.squareup.okhttp3:okhttp:3.14.0'
//Retrofit依赖
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
//GSON依赖
implementation 'com.google.code.gson:gson:2.8.5'
//GSON转换器依赖
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'

依赖这边这个坑,retrofit的版本要和converter的版本保持一致,否则Json和对象之间的转换可能会报错。

(2)一般用法
public interface SearchFileAPIService {

    @FormUrlEncoded
    @POST("file/search?from=upload")
    Call<ResponseBody> fileSearch(@Field("filetype") String filetype, @Field("filename") String filename);

}

我们先来看一下retrofit的基本代码,以上代码正是retrofit的post请求。
之所以在文章一开头就贴出基本代码是因为需要说明以下几点:

(1) 本文重点介绍Retrofit,与RxJava结合使用将在下节介绍;
(2) retrofit用于接口的封装,结合OKHttp可以优雅的实现网络请求框架;
(3) retrofit第一步总是声明接口,以上代码声明了SearchFileAPIService接口,我们可以在SearchFileAPIService声明多个方法,以上代码只封装了fileSearch方法,retrofit提供了多种注解,@FormUrlEncoded@POST@Field都是retrofit的注解,当然还有其它注解,文章后面会讲解;
(4) baseUrl有两种,一种不带路径,比如:http://xxxxxx:82,另一种带路径,比如: http://xxxxxx:82/oa/,这里需要重点注意:不带路径的baseUrl结尾可以不带有'/',但是带路径的baseUrl接口必须以'/'结尾,否则会报错,如图:

图片.png

(5) Call后面必须添加泛型,否则会报错,泛型类型不允许是StringInteger或者其他基本数据类型,这里用将ResponseBody作为泛型类型即可,ResponseBody是OKHttp中的类,所以Retrofit有时候需要结合OKHttp使用。

其实需要注意的不止是以上5点,还有很多需要注意的地方,如果过早的指出那就更加不能理解了。

以上声明的5点只是打一个预防针,文章后面会重新说明。

(3)Retrofit的请求方式注解

GET请求是请求方式的其中一种,下面我来封装一个最简单的GET请求接口

public interface SearchFileAPIService {
    @GET("/")
    Call<ResponseBody> getBaidu();
}
    Retrofit retrofit = new Retrofit.Builder().baseUrl("http://www.baidu.com")
            .build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ResponseBody> call = searchFileAPIService.getBaidu();
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", "onResponse:"+response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.d("aaa", "onFailure:"+t.getMessage());
        }
    });

请求结果如下:

图片.png

POST请求是请求方式的一种,POST请求上面已经给出例子了。

@HTTP可以使用任何请求,现在就以GET请求为例

public interface SearchFileAPIService {

    @HTTP(method = "GET", path = "user_user", hasBody = false)
    Call<ResponseBody> getBaidu3();

}
    Retrofit retrofit = new Retrofit.Builder().baseUrl("http://www.baidu.com")
            .build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ResponseBody> call = searchFileAPIService.getBaidu3();
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", "onResponse:"+response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.d("aaa", "onFailure:"+t.getMessage());
        }
    });

以上代码请求网络需要跳过证书(怎么跳过证书文章后面会讲到)

请求头报文和上面一样:

图片.png

DELETE请求相对GET和POST请求而言用的比较少

public interface SearchFileAPIService {

    @HTTP(method = "DELETE", path = "delete", hasBody = true)
    Call<ResponseBody> deleteSomething();

}

或者

public interface SearchFileAPIService {

    @DELETE("/{delete}")
    Call<ResponseBody> deleteSomething(@Path("delete") String delete);

}
    Retrofit retrofit = new Retrofit.Builder().baseUrl("http://www.baidu.com")
            .build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ResponseBody> call = searchFileAPIService.deleteSomething("delete_delete");
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", "onResponse:"+response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else{
                Log.d("aaa", "onResponse:"+response.message());
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.d("aaa", "onFailure:"+t.getMessage());
        }
    });

以上代码请求网络需要跳过证书(怎么跳过证书文章后面会讲到)

目前当前接口调试是不通的,大家也不要纠结为什么没用了,到目前为止我也没用过这个请求,以后用到的话可以补充。不过查询资料之后得到一句解释:

DELETE请求顾名思义,就是执行相应的删除操作,配合数据库进行相应的删除动作。

用于更新资源

该请求是对put请求的补充,用于更新局部资源

(以后补充)

(以后补充)

(4)Retrofit的请求参数注解
public interface SearchFileAPIService {
    @GET("/{user}")
    Call<ResponseBody> getBaidu2(@Path("user") String user);
}
    Retrofit retrofit = new Retrofit.Builder().baseUrl("http://www.baidu.com")
            .build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ResponseBody> call = searchFileAPIService.getBaidu2("user_user");
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", "onResponse:"+response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.d("aaa", "onFailure:"+t.getMessage());
        }
    });

以上代码请求网络需要跳过证书(怎么跳过证书文章后面会讲到)

请求头如下:

图片.png

通过以上代码演示,@Path的作用已经显而易见了,@GET("/{user}")中的user是一个参数,参数变量用{}修饰。

@Filed@FiledMap主要用于POST请求表单数据的声明,我们来看一下接口的定义

public interface SearchFileAPIService {

    @FormUrlEncoded
    @POST("file/search?from=upload")
    Call<ResponseBody> fileSearch(@Field("filetype") String filetype, @Field("filename") String filename);
    @FormUrlEncoded
    @POST("file/search?from=upload")
    Call<ResponseBody> fileSearch2(@FieldMap Map<String, String> map)

}

下面贴一下完整的使用

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://xxxxxxxx:82/oa/").build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ResponseBody> call = searchFileAPIService.fileSearch("-1", "1");
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call call, Throwable t) {
            Log.d("aaa", t.getMessage());
        }
    });
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http:/xxxxxxxxx:82/oa/").build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Map<String, String> map = new HashMap();
    map.put("filetype", "-1");
    map.put("filename", "1");
    Call<ResponseBody> call = searchFileAPIService.fileSearch2(map);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call call, Throwable t) {
            Log.d("aaa", t.getMessage());
        }
    });

在post请求时,我们可以传递键值对,也可以传递键值对的map集合,使用@Body我们可以传递一个对象,利用json转换器将对象转成json,代码如下:

public interface SearchFileAPIService {

    @POST("file/search?from=upload")
    Call<ResponseBody> fileSearch3(@Body FileBean fileBean);

}
    Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(new Gson()))
            .baseUrl("http://xxxxxxxxxx:82/oa/").build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    FileBean fileBean = new FileBean();
    fileBean.setFiletype("-1");
    fileBean.setFilename("1");
    Call<ResponseBody> call = searchFileAPIService.fileSearch3(fileBean);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call call, Throwable t) {
            Log.d("aaa", t.getMessage());
        }
    });

这里使用了addConverterFactory,这是添加转换器,文章后面会讲到。

一般情况下,请求路径是在@POST的参数中声明的,一旦使用@Url来指定请求路径,@POST就不能传递传输。代码如下:

    public interface SearchFileAPIService {
    
            @POST()
            Call<ResponseBody> fileSearch4(@Url String url, @Body FileBean fileBean);
    
    }
    Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(new Gson()))
            .baseUrl("http://xin-ikea.cn:82/oa/").build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    FileBean fileBean = new FileBean();
    fileBean.setFiletype("-1");
    fileBean.setFilename("1");
    Call<ResponseBody> call = searchFileAPIService.fileSearch4("file/search?from=upload", fileBean);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call call, Throwable t) {
            Log.d("aaa", t.getMessage());
        }
    });

我定义了一个接口

    @FormUrlEncoded
    @POST("file/search?from=upload")
    Call<ResponseBody> fileSearch5(@Query("filetype") String filetype, @Query("filename") String filename, @Field("filetype") String filetype1, @Field("filename") String filename1);

抓到的报文如下:

图片.png

我们发现在原本URL的基础上拼接了filetype和filename两个参数,所以 @Query@QueryMap其实主要用于GET请求。接口如下:

    @GET("/")
    Call<ResponseBody> getJianshu1(@Query("name") String name, @Query("age") int age);

    @GET("/")
    Call<ResponseBody> getJianshu2(@QueryMap Map<String, String> map);

@Part:用于表单字段,Part和PartMap与Multipart注解结合使用,适合文件上传的情况

@PartMap:用于表单字段,默认接受的类型是Map<String,REquestBody>,可用于实现多文件上传

这两种注解将在文章下面和Multipart注解一起讲解。

(5)Retrofit响应格式注解

@FormUrlEncoded@Field@FieldMap一起配合使用,用于POST请求传递表单数据。

    public interface SearchFileAPIService {

            @FormUrlEncoded
            @POST("file/search?from=upload")
            Call<ResponseBody> fileSearch(@Field("filetype") String filetype, @Field("filename") String filename);
            @FormUrlEncoded
            @POST("file/search?from=upload")
            Call<ResponseBody> fileSearch2(@FieldMap Map<String, String> map);

    }

一般和@Part@PartMap一起配合使用,支持单文件上传,多文件上传,也支持表单和文件一起上传。

代码如下:

    public interface SearchFileAPIService {

            @Multipart
            @POST("FileUpload/FileUploadServlet")
            Call<ResponseBody> uploadFlie2(@Part MultipartBody.Part file);
    }
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://192.168.0.105:8080").build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);

    File file = new File(Environment.getExternalStorageDirectory() + File.separator + "iam.jpg");

    // 创建 RequestBody
    //application/otcet-stream
    RequestBody requestFile = RequestBody.create(MediaType.parse("application/otcet-stream"), file);

    //新建Part
    MultipartBody.Part body = MultipartBody.Part.createFormData("photo1", file.getName(), requestFile);

    // 添加描述
    String descriptionString = "hello, 这是文件描述";
    RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString);
    Call<ResponseBody> call = searchFileAPIService.uploadFlie2(body);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call call, Throwable t) {
            Log.d("aaa", t.getMessage());
        }
    });

我们查看一下报文:

图片.png

该注解可以用于下载文件。
代码如下:

    public interface SearchFileAPIService {
            @Streaming
            @GET("/1.apk")
            Call<ResponseBody> downloadFile();
    }
    Retrofit retrofit = new Retrofit.Builder().baseUrl("http://192.168.0.105:8080").build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ResponseBody> call = searchFileAPIService.downloadFile();
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                boolean writtenToDisk = writeResponseBodyToDisk(response.body());
                Log.d("aaa", "下载成功:"+writtenToDisk);
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.d("aaa", "下载失败");
        }
    });
//写入到磁盘根目录
private boolean writeResponseBodyToDisk(ResponseBody body) {
    try {
        File futureStudioIconFile = new File(Environment.getExternalStorageDirectory() + File.separator + "myapk.apk");
        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            byte[] fileReader = new byte[4096];

            final long fileSize = body.contentLength();
            long fileSizeDownloaded = 0;

            inputStream = body.byteStream();
            outputStream = new FileOutputStream(futureStudioIconFile);
            while (true) {
                int read = inputStream.read(fileReader);

                if (read == -1) {
                    break;
                }

                outputStream.write(fileReader, 0, read);

                fileSizeDownloaded += read;


                final long finalFileSizeDownloaded = fileSizeDownloaded;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        bt_1.setText("file download: " + finalFileSizeDownloaded + " of " + fileSize);
                    }
                });
            }

            outputStream.flush();

            return true;
        } catch (IOException e) {
            return false;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }

            if (outputStream != null) {
                outputStream.close();
            }
        }
    } catch (IOException e) {
        return false;
    }
}

报文如下:

图片.png
(6)Retrofit的请求头注解

用于添加固定请求头,可以同时添加多个。通过该注解添加的请求头不会相互覆盖,而是共同存在。

    @Headers({"User-Agent:okhttp/3.14.1","User-Agent:okhttp/3.14.2","Content-Type: text/html"})
    @GET("/")
    Call<ResponseBody> getJianshu2();

请求报文如下:

图片.png

作为方法的参数传入,用于添加不固定值的Header,该注解会更新已有的请求头

    @GET("/")
    Call<ResponseBody> getJianshu2(@Header("Content-Type") String contentType);
    Retrofit retrofit = new Retrofit.Builder().baseUrl("http://www.jianshu.com").build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ResponseBody> call = searchFileAPIService.getJianshu2("text/html");
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                Log.d("aaa", "11111111111111111");
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.d("aaa", "2222222222222222");
        }
    });

报文如下:

图片.png
(7)怎么跳出SSL证书校验?

有时候,我们想要请求https开头的链接,有些服务器会做限制,不让别人访问自己的服务器,这个时候我们需要跳出证书校验了,Retrofit的client方法可以重新封装OkHttpClient,使hostnameVerifier返回true即可跳过证书校验。

就以访问“https://www.jianshu.com”为例,代码如下:

public class SslClient {

    private SslClient(){}

    static class SingleHolder{
        public static SslClient instance = new SslClient();
    }

    public static SslClient getInstance(){
        return SingleHolder.instance;
    }

    public OkHttpClient getOkHttpClient(){
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        X509TrustManager x509TrustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };

        TrustManager[] trustManager = new TrustManager[]{
                x509TrustManager
        };
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustManager, new SecureRandom());
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
            builder.sslSocketFactory(sslSocketFactory,x509TrustManager);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return hostname.contains("www.jianshu.com");
                }
            });

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return builder.build();
    }

}
    public interface SearchFileAPIService {

            @GET("/")
            Call<ResponseBody> getJianshu();

    }
    Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.jianshu.com")
            .client(SslClient.getInstance().getOkHttpClient())
            .build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ResponseBody> call = searchFileAPIService.getJianshu();
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", "onResponse:"+response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else{
                Log.d("aaa", "onResponse:"+response.message());
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.d("aaa", "onFailure:"+t.getMessage());
        }
    });
(8)转换器

我们先来搜索一下有多少转换器依赖吧

图片.png

这里就以gson转换器为例,其它转换器不做讲解。

一般情况下,我们的post请求代码是这样写的

    Retrofit retrofit = new Retrofit.Builder().baseUrl("http://123.124.175.239:7001").build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ResponseBody> call = searchFileAPIService.getCarList("868256021322879", "862679", "c907d5df8b26550eaf2841ed9bcf51bb44b9ae1b", "d3974829a20747579c90e2004a5ed1c5");
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if(response != null && response.isSuccessful()){
                try {
                    Log.d("aaa", response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {

        }
    });

当我们获取返回结果时,发现返回结果时一个json或者json数组,这个时候我们可以利用转换器将json直接转成对象,改造之后的代码如下:

    public interface SearchFileAPIService {

            @FormUrlEncoded
            @POST("/xxx/interface/carList")
            Call<ArrayList<Car>> getCarList(@Field("IMEI") String IMEI, @Field("appid") String appid, @Field("appkey") String appkey, @Field("userId") String userId);

    }
    Retrofit retrofit = new Retrofit.Builder().baseUrl("http://123.124.175.239:7001")
            .addConverterFactory(GsonConverterFactory.create(new Gson()))
            .build();
    SearchFileAPIService searchFileAPIService = retrofit.create(SearchFileAPIService.class);
    Call<ArrayList<Car>> call = searchFileAPIService.getCarList("868256021322879", "862679", "c907d5df8b26550eaf2841ed9bcf51bb44b9ae1b", "d3974829a20747579c90e2004a5ed1c5");
    call.enqueue(new Callback<ArrayList<Car>>() {
        @Override
        public void onResponse(Call<ArrayList<Car>> call, Response<ArrayList<Car>> response) {
            if(response != null && response.isSuccessful()){
                ArrayList<Car> carlist = response.body();
                for(Car car : carlist){
                    Log.d("aaa", car.getCarNumber());
                }
            }
        }

        @Override
        public void onFailure(Call<ArrayList<Car>> call, Throwable t) {

        }
    });

获取的结果是一个数组:

图片.png
(9)日志拦截器

当我们网络请求时,要想看到报文,有时候必须依赖于抓包工具,本人常用的抓包工具是Fiddler,除了抓包工具之外,OkHttp提供了日志拦截器,可以打印报文日志。

通过下图代码,可以添加拦截求

图片.png

创建日志拦截器有两种方式:

/**
 * 创建日志拦截器
 *
 * @return
 */
public class LogInterceptor implements Interceptor {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Log.d("bbb", "请求数据:");
        Log.d("bbb", "请求URL:"+String.valueOf(request.url()));
        Log.d("bbb", "请求头:"+String.valueOf(request.headers()));
        Log.d("bbb", "请求体:"+request.toString());

        okhttp3.Response response = chain.proceed(request);

        Log.d("bbb", "响应数据:");
        Log.d("bbb", "返回码:"+String.valueOf(response.code()));
        Log.d("bbb", "响应头:"+String.valueOf(response.headers()));
        Log.d("bbb", "响应体:"+String.valueOf(response.body().string()));

        return response;
    }
}

打印日志如下:

图片.png
implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0'
/**
 * 创建日志拦截器
 *
 * @return
 */
public static HttpLoggingInterceptor getHttpLoggingInterceptor() {
    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(
            new HttpLoggingInterceptor.Logger() {

                @Override
                public void log(String message) {
                    Log.e("bbb", "log = " + message);
                }

            });
    loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    return loggingInterceptor;
}

捕获到的日志如下:

图片.png
(10)自定义CookieJar
            OkHttpClient client = new OkHttpClient.Builder()
                    .addInterceptor(getHttpLoggingInterceptor())
                    .cookieJar(new CookieJar() {
                        final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();

                        @Override
                        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                            cookieStore.put(url, cookies);//保存cookie
                            //也可以使用SP保存
                        }

                        @Override
                        public List<Cookie> loadForRequest(HttpUrl url) {
                            List<Cookie> cookies = cookieStore.get(url);//取出cookie
                            return cookies != null ? cookies : new ArrayList<Cookie>();
                        }
                    })
                    .build();
            Retrofit retrofit = new Retrofit.Builder().baseUrl("http://123.124.175.239:7001")
                    .addConverterFactory(GsonConverterFactory.create(new Gson()))
                    .client(client)
                    .build();
(11)取消请求
call.cancel(); 
上一篇下一篇

猜你喜欢

热点阅读