Android Retrofit+OkHttp

154 阅读4分钟

OkHttp 介绍

OkHttp 是一个高效的 Http请求框架 ,旨在 简化 客户端网络请求,提高 请求效率。

  • 连接复用 :避免在每个请求之间重新建立连接。
  • 连接池 :降低了请求延迟 (HTTP/2不可用情况下);
  • 自动重试 :在请求失败时自动重试请求,从而提高请求可靠性。
  • 自动处理缓存 :会按照预定的缓存策略处理缓存,以便最大化网络效率。
  • 支持HTTP/2 : 并且允许对同一个主机的所有请求共享一个套接字(HTTP/2);
  • 简化Api :Api设计简单明了,易于使用,可以轻松发起请求获取响应,并处理异常。
  • 支持gzip压缩 :OkHttp支持gzip压缩,以便通过减少网络数据的大小来提高网络效率。

image.png

private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .connectTimeout(8, TimeUnit.SECONDS)
    .readTimeout(8, TimeUnit.SECONDS)
    .hostnameVerifier((hostname, session) -> true)
    .build();
Request request = new Request.Builder()
    .url(url)
    .post(RequestBody.create(jsonObjectParams.toString(), JSON))
    .build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
    if (response.isSuccessful())
        resultInfo.parseJson(Objects.requireNonNull(response.body()).string());
    MyLog.d("-----http post " + url + "    onResponse:" + resultInfo.toString());
    resultInfoMutableLiveData.postValue(resultInfo);
    response.close();
}

@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
    MyLog.d("-----http post ret onFailure : " + e);
    resultInfoMutableLiveData.postValue(resultInfo);
//                        call.cancel();
}
});//得到Response 对象

Okhttp 之 分发器

Dispatcher 内部维护队列与线程池,完成请求调配。 阻塞队列

OkHttp 之 拦截器

Intercepter 完成整个请求过程;

.addInterceptor().build()

public void addInterceptor(){
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    httpClient.addInterceptor(logging);
    retrofit.newBuilder().client(httpClient.build()).build();
}

OkHttp 之 缓存和cookie

Retrofit 介绍

Retrofit 是一个 RESTful 规范的 HTTP 网络请求框架的封装,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装

github.com/square/retr…

  • OkHttp、okio、Retrofit是 Square 是网络层三板斧
  • Retrofit 依赖 OkHttp
  • Retrofit 可以结合 RxJava

RESTful规范

public interface Api {
    @GET("user")
    Call<ResponseBody> getUserNoConvertCallAdapter(@QueryMap Map<String, Object> map);


    @GET("user")
    Call<ApiResponseBean> getUserNoCallAdapter(ApiRequestBean apiRequestBean);
}

依赖

implementation 'com.squareup.retrofit2:retrofit:2.11.0'

Retrofit 之 设计模式

Retrofit 之 ServiceMethod

1. HttpMethod

表示HTTP请求的方法类型,如GET、POST、PUT等。

2. RequestFactory

用于创建Request对象的工厂类。RequestFactory根据ServiceMethod中的信息(如URL、请求头、请求体等)构建Request对象。

3. ResponseType

表示HTTP响应的类型。这可以是一个自定义的类型,也可以是Retrofit提供的标准类型(如ResponseBody等)。

4. CallAdapterFactory

用于创建CallAdapter的工厂类。CallAdapter用于将HTTP响应转换为适合您的方法返回值的类型。

5. ConverterFactory

用于创建Converter的工厂类。Converter用于将HTTP响应体转换为指定的Java类型。

Retrofit 之 Converter 数据解析器

Converter

  • OkHttp 拦截器是对 OkHttpClient 与服务器之间的 HTTP 请求进行拦截,处理。

  • Converter 是 Retrofit 对于请求的对象和返回的 Body 等进行转换。

使用数据解析器代码:

public ApiResponseBean getUserNoCallAdapter(){
    ApiRequestBean apiRequestBean = new ApiRequestBean();
    apiRequestBean.setId(10086);
    apiRequestBean.setName("ljj");
    Call<ApiResponseBean> call = retrofit.create(Api.class).getUserNoCallAdapter(apiRequestBean);
    Response<ApiResponseBean> response =null;
    try {
        response=  call.execute();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return response.body();
}

Retrofit 之 CallAdapter 解析

For Example

GsonConverterFactory.class

package com.example.retrofit;

import android.util.Log;


import com.example.retrofit.bean.ApiResponse;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.Charset;

import io.reactivex.rxjava3.annotations.Nullable;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okio.Buffer;
import retrofit2.Converter;
import retrofit2.Retrofit;

public class GsonConverterFactory extends Converter.Factory {

    public static final String TAG = GsonConverterFactory.class.getSimpleName();
    private final Gson gson;

    private GsonConverterFactory(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        this.gson = gson;
    }

    public static GsonConverterFactory create() {
        return create(new Gson());
    }

    public static GsonConverterFactory create(Gson gson) {
        return new GsonConverterFactory(gson);
    }


    @Nullable
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonResponseBodyConverter<>(gson, adapter);
    }

    @Nullable
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonRequestBodyConverter(gson, adapter);
    }

    private final static class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {

        private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
        private static final Charset UTF_8 = Charset.forName("UTF-8");

        private final Gson gson;
        private final TypeAdapter<T> adapter;

        GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
            this.gson = gson;
            this.adapter = adapter;
        }

        @Override public RequestBody convert(T value) throws IOException {
            Buffer buffer = new Buffer();
            Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);

            JsonWriter jsonWriter = gson.newJsonWriter(writer);
            adapter.write(jsonWriter, value);
            jsonWriter.close();
            return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
        }
    }

    private final static class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
        private final Gson gson;
        private final TypeAdapter<T> adapter;

        GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
            this.gson = gson;
            this.adapter = adapter;
        }

        @Override public T convert(ResponseBody value) throws IOException {
            JsonReader jsonReader = gson.newJsonReader(value.charStream());
            try {
                T entity = adapter.read(jsonReader);
                if(entity instanceof ApiResponse){
                    ApiResponse result = (ApiResponse) entity;
                    if(!result.isSuccess()){
                        if(result.getMsg() != null){
                            Log.v(TAG, "convert: " + result.getMsg());
                        }
                    }
                }
                return entity;
            }catch (Exception e){
                e.printStackTrace();
                throw e;
            } finally {
                value.close();
            }
        }
    }
}
package com.example.retrofit;

import android.util.ArrayMap;

import com.example.retrofit.bean.ApiRequestBean;
import com.example.retrofit.bean.ApiResponseBean;
import com.google.gson.Gson;

import java.io.IOException;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;

public class RetrofitManager {

    private static volatile RetrofitManager instance = null;
    private final Retrofit retrofit;

    private RetrofitManager() {  //避免类在外部被实例化
        retrofit = new Retrofit.Builder()
                .baseUrl("http://fanyi.youdao.com/") //设置网络请求的Url地址
                .addConverterFactory(GsonConverterFactory.create()) //设置数据解析器
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())//单独依赖库 retofit2.adapter.Rxjava3
                .build();
    }

    //创建对象的外部方法
    public static synchronized RetrofitManager getInstance() {
        if (null == instance) {
            instance = new RetrofitManager();
        }
        return instance;
    }

    public ApiResponseBean getUserNoCallAdapter(){
        ApiRequestBean apiRequestBean = new ApiRequestBean();
        apiRequestBean.setId(10086);
        apiRequestBean.setName("ljj");
        Call<ApiResponseBean> call = retrofit.create(Api.class).getUserNoCallAdapter(apiRequestBean);
        Response<ApiResponseBean> response =null;
        try {
            response=  call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response.body();
    }

    public ApiResponseBean getUserNoConvertCallAdapter(){
        ArrayMap map = new ArrayMap();
        map.put("id",10086);
        map.put("name","llj");

        Call<ResponseBody> call = retrofit.create(Api.class).getUserNoConvertCallAdapter(map);

        Response<ResponseBody> response = null;
        try {
            response = call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ApiResponseBean apiResponseBean = new ApiResponseBean();
        if (response.isSuccessful()) {
            try {
                apiResponseBean = new Gson().fromJson(response.body().string(),ApiResponseBean.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return apiResponseBean;
    }
}