Retrofit 2.5 框架使用與源碼分析

Retrofit 框架使用

請求內容與返回值

使用PostMan進行請求測試 請求:https://api.github.com/search/repositories?q=androidhtml

返回值:java

Header:node

Body:android

{
         "total_count": 943593,
         "incomplete_results": false,
         "items": [
         {
            "id": 82128465,
            "node_id": "MDEwOlJlcG9zaXRvcnk4MjEyODQ2NQ==",
            "name": "Android",
            "full_name": "open-android/Android",
            "private": false,
            "owner": {
                "login": "open-android",
                "id": 23095877,
                "node_id": "MDQ6VXNlcjIzMDk1ODc3",
                "avatar_url": "https://avatars2.githubusercontent.com/u/23095877?v=4",
                //……
             },
            "html_url": "https://github.com/open-android/Android",
            "description": "GitHub上最火的Android開源項目,全部開源項目都有詳細資料和配套視頻",
            "fork": false,
            "url": "https://api.github.com/repos/open-android/Android",
            //……
         },
         {
            "id": 12544093,
            "node_id": "MDEwOlJlcG9zaXRvcnkxMjU0NDA5Mw==",
            "name": "Android",
            "full_name": "hmkcode/Android",
                "private": false,
                "owner": {
                    "login": "hmkcode",
                    "id": 3790597,
                //……
                },
                //……
            }
         ]
    }
複製代碼

引入Retrofit依賴

implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
複製代碼

根據返回的請求結果定義Repository Bean類

返回的報文采用google.gson進行處理,金處理必要的值git

public class RepoBean {

    //用於表示Repo id
    private int id;
    //用於表示RepoName
    private String name;

    //用於表示完整名稱
    //Repository中json的返回值爲 `full_name`,與定義的變量名不一致,使用註解`@SerializedName`進行標註
    @SerializedName("full_name")
    private String fullName;
    //省略getter和setter
    //……
}

複製代碼

根據返回的請求結果定義一次查詢結果

public class SearchRepoBean {

    //用於表示倉庫數量
    @SerializedName("total_count")
    private int totalCount;
    //用於表示是否爲完整結果
    private boolean incompleteResults;
    //用於表示持有的全部的倉庫類
    private List<RepoBean>items;

    //省略getter和setter
    //……
}

複製代碼

定義網絡請求API接口

public interface GithubService {
    //@Get註解,表示以Get方法發送網絡請求
    //返回類型爲Call<SearchRepoBean>,SearchRepoBean是接收數據的類,能夠自定義
    @GET("search/repositories")
    Call<SearchRepoBean> getRepoInfo(@Query("q") String query);
}

複製代碼

初始化Retrofit實例,生成接口實現類

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/") //設置網絡請求的URL地址
.addConverterFactory(GsonConverterFactory.create()) //設置數據解析器
.build();

githubService = retrofit.create(GithubService.class);

複製代碼

進行網絡請求

Call<SearchRepoBean> call = githubService.getRepoInfo("Android");
    //同步請求方式
    //call.request();
    //異步請求方式
    call.enqueue(new Callback<SearchRepoBean>() {
         @Override
          public void onResponse(Call<SearchRepoBean> call, Response<SearchRepoBean> response) {
         //輸出請求結果
         // LogUtils.printInfo("搜索到的倉庫的數量:" + response.body().getItems().size());
         // List<RepoBean>repoBeans=new ArrayList<>();
         // repoBeans.addAll(response.body().getItems());
         // for (int i=repoBeans.size()-1;i>=0;i--){
          // LogUtils.printInfo(repoBeans.get(i).getFullName());
         }
     }

        @Override
        public void onFailure(Call<SearchRepoBean> call, Throwable t) {
        }
    });
複製代碼

將請求值的返回設爲LiveData

將請求的返回值設爲LiveData能夠經過爲Retrofit添加CallAdapterFactory來實現github

public interface GithubService {
        @GET("search/repositories")
        LiveData<SearchRepoBean> getRepoInfo(@Query("q") String query);
    }
複製代碼

自定義LiveDataCallAdapterFactoryjson

public class LiveDataCallAdapterFactory extends CallAdapter.Factory {

    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {

    //用於獲取泛型的參數
    Type observerType = getParameterUpperBound(0, (ParameterizedType) returnType);

    Class<?> rawObserverType = getRawType(observerType);


    LiveDataCallAdapter<Object> liveDataCallAdapter = new LiveDataCallAdapter<>(rawObserverType);

    return liveDataCallAdapter;
    }
}


複製代碼

自定義 LiveDataCallAdapterapi

public class LiveDataCallAdapter<R> implements CallAdapter<R, LiveData<SearchRepoBean>> {

    private Type responseType;

    public LiveDataCallAdapter(Type responseType){
    this.responseType=responseType;
    }

    @Override
    public Type responseType() {
    return responseType;
    }

    @Override
    public LiveData<SearchRepoBean> adapt(final Call<R> call) {

    LiveData<SearchRepoBean>searchRepoBeanLiveData=new LiveData<SearchRepoBean>() {

        @Override
        protected void onActive() {
            super.onActive();
            call.enqueue(new Callback<R>() {
                @Override
                public void onResponse(Call<R> call, Response<R> response) {
                postValue((SearchRepoBean) response.body());
        }

        @Override
        public void onFailure(Call<R> call, Throwable t) {
                LogUtils.printInfo("error");
            }
        });
    }
  };
    //這裏的return 即爲下文中githubService.getRepoInfo("Android")調用的返回值
    return searchRepoBeanLiveData;
 }
}

複製代碼

爲Retrofit實例添加CallAdapterFactory緩存

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(new LiveDataCallAdapterFactory())
    .build();

複製代碼

調用方法網絡

repoBeanLiveData = githubService.getRepoInfo("Android");
    repoBeanLiveData.observe(GithubApiActivity.this, new Observer<SearchRepoBean>() {
        @Override
        public void onChanged(SearchRepoBean searchRepoBean) {
        //輸出結果
        }
    });

複製代碼

添加通用的響應實體

經過LiveDataCallAdapterLiveDataCallAdapterFactory 能夠將返回的數據表示爲LiveData數據形式,且只能對返回結果爲SearchRepoBean類型的JSON字符串進行處理。若是是返回其餘的實體則須要從新構造適配器。

定義一個通用的響應實體

public class ApiResponse<T> {

    public ApiResponseSuccess<T> create(Response<T> response) {
        if (response.isSuccessful()) {
            return new ApiResponseSuccess<T>(response.body());
        } else {
            return null;
            }
    }

//用於表示返回成功的值
    public static class ApiResponseSuccess<T> extends ApiResponse<T> {
        /用於表示請求返回成功的內容,在本代碼中是SearchRepoBean
        private T body;

        public ApiResponseSuccess(T body) {
        this.body = body;
    }

    public T getBody() {
        return body;
    }
    }
}

複製代碼

修改LiveDataCallAdapterFactory

public class LiveDataCallAdapterFactory extends CallAdapter.Factory {

    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        //用於獲取泛型的參數
        //return type爲LiveData<ApiResponse<SearchRepoBean>>
        //observerType爲ApiResponse<SearchRepoBean>
        Type observerType = getParameterUpperBound(0, (ParameterizedType) returnType);
        //bodyType爲SearchRepoBean
        Type bodyType = getParameterUpperBound(0, (ParameterizedType) observerType);
        LiveDataCallAdapter<Object> liveDataCallAdapter = new LiveDataCallAdapter<>(bodyType);

    return liveDataCallAdapter;
}
}

複製代碼

修改LiveDataCallAdapter

public class LiveDataCallAdapter<R> implements CallAdapter<R,LiveData<ApiResponse<R>>> {

    private Type responseType;

    public LiveDataCallAdapter(Type responseType){
        this.responseType=responseType;
    }

    @Override
    public Type responseType() {
        return responseType;
    }

    @Override
    public LiveData<ApiResponse<R>> adapt(final Call<R> call) {
        LiveData<ApiResponse<R>> result=new LiveData<ApiResponse<R>>() {
            @Override
            protected void onActive() {
                super.onActive();
                call.enqueue(new Callback<R>() {
            @Override
            public void onResponse(Call<R> call, Response<R> response) {
                postValue(new ApiResponse<R>().create(response));
            }

            @Override
            public void onFailure(Call<R> call, Throwable t) {
            // LogUtils.printInfo("+++++!2312qwqweww31");
            }
            });
        }
        };
    return result;
    }
}
複製代碼

修改調用方法

repoBeanLiveData = githubService.getRepoInfo("Android");
    repoBeanLiveData.observe(GithubApiActivity.this, new Observer<ApiResponse<SearchRepoBean>>() {
    @Override
    public void onChanged(ApiResponse<SearchRepoBean> searchRepoBeanApiResponse) {
        SearchRepoBean searchRepoBean = (SearchRepoBean) ((ApiResponse.ApiResponseSuccess) searchRepoBeanApiResponse).getBody();
        //輸出結果
     }
    });

複製代碼

源碼詳解

Retrofit構建中的.baseUrl("https://api.github.com/")介紹

Retrofit源碼,Retrofit在源碼中使用建造者模式進行實例化,將String類型的地址轉換爲OKhttp3中的HttpUrl類型

public final class Retrofit {

    public static final class Builder {
    public Builder baseUrl(String baseUrl) {
        checkNotNull(baseUrl, "baseUrl == null");
        return baseUrl(HttpUrl.get(baseUrl));
    }
    public Builder baseUrl(HttpUrl baseUrl) {
        checkNotNull(baseUrl, "baseUrl == null");
        List<String> pathSegments = baseUrl.pathSegments();
        if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
            throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
        }
        this.baseUrl = baseUrl;
        return this;
    }
    }
}

複製代碼
Retrofit構建中的.addConverterFactory(GsonConverterFactory.create())

經過.addConverterFactory()傳入咱們須要的ConverFactory,目的是將responseBody轉換成咱們的Bean類,在這裏咱們使用的是GsonConverterFactory

public Builder addConverterFactory(Converter.Factory factory) {
        converterFactories.add(checkNotNull(factory, "factory == null"));
        return this;
    }

複製代碼

Converter接口源碼,核心是T convert(F value),將F類型的數據轉換爲T類型

public interface Converter<F, T> {
    //將F類型的數據轉換爲T類型
    @Nullable T convert(F value) throws IOException;

    //根據數據類型建立Converter建立 Converter
    abstract class Factory {
        //將HTTP響應的body體轉換成type,type是由CallAdapter 接口裏面的responseType()函數返回的。
        public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
        return null;
    }

    //將API方法的輸入參數使用註解@Body, @Part 和 @PartMap標記的類型,從type轉換爲RequestBody
    public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return null;
    }
    //將API方法的輸入參數使用註解@Header, @HeaderMap, @Path, @Query 和 @QueryMap 標記的類型從type轉換爲String
    public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
        return null;
    }

    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
        return Utils.getParameterUpperBound(index, type);
    }

    protected static Class<?> getRawType(Type type) {
        return Utils.getRawType(type);
        }
    }
}

複製代碼
Retrofit構建中的.addCallAdapterFactory(new LiveDataCallAdapterFactory())

用於添加數據適配器,在HttpServiceMethod實例生成的時候會調用

public final class Retrofit {
    final List<CallAdapter.Factory> callAdapterFactories;
    //…………
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
        callAdapterFactories.add(checkNotNull(factory, "factory == null"));
        return this;
    }
    //…………
}

複製代碼
最終用來建立Service的代碼retrofit.create(GithubService.class)

create()採用代理的方式進行建立,

public final class Retrofit {
    //……
    public <T> T create(final Class<T> service) {
    //判判定義的接口服務是否可用
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
        eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
        private final Platform platform = Platform.get();
        private final Object[] emptyArgs = new Object[0];

        @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
        // 若是是Object自己的方法,正常調用後返回
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(this, args);
    }
        //若是是platform默認的方法,正常調用後返回
        if (platform.isDefaultMethod(method)) {
        return platform.invokeDefaultMethod(method, service, proxy, args);
    }
//解析咱們定義的網絡請求的方法
    return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
     }
    });
}
//……
}
複製代碼

loadServiceMethod(Method method)源碼解析,其其實是HttpServiceMethod對象

ServiceMethod<?> loadServiceMethod(Method method) {
    //從解析的緩存中獲取
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                result = ServiceMethod.parseAnnotations(this, method);
                serviceMethodCache.put(method, result);
            }
      }
    return result;
    }

複製代碼

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method)源碼

abstract class ServiceMethod<T> {
        static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        //RequestFactory負責解析接口而且生成Request
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

        //…………
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
         }

        abstract T invoke(Object[] args);
    }


複製代碼

HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)源碼

//將一個接口方法轉變爲一個Http請求
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {

    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) {
        //建立HTTP請求的CallAdapter,在下面有createCallAdapter()源碼
        CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
        //……
        Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

        okhttp3.Call.Factory callFactory = retrofit.callFactory;
            return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
        }

        private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter( Retrofit retrofit, Method method) {
            Type returnType = method.getGenericReturnType();
            Annotation[] annotations = method.getAnnotations();
        try {
            //retrofit.callAdapter()返回 Retrofit實例化中.addCallAdapterFactory(new LiveDataCallAdapterFactory())添加的CallAdapter
            return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
        } catch (RuntimeException e) { // Wide exception range because factories are user code.
             throw methodError(method, e, "Unable to create call adapter for %s", returnType);
        }
}

//…………

    private final RequestFactory requestFactory;
    private final okhttp3.Call.Factory callFactory;
    private final CallAdapter<ResponseT, ReturnT> callAdapter;
    private final Converter<ResponseBody, ResponseT> responseConverter;

    private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory, CallAdapter<ResponseT, ReturnT> callAdapter, Converter<ResponseBody, ResponseT> responseConverter) {
        this.requestFactory = requestFactory;
        this.callFactory = callFactory;
        this.callAdapter = callAdapter;
        this.responseConverter = responseConverter;
    }

    //代理調用的invoke最終會調用下面invoke方法
    @Override ReturnT invoke(Object[] args) {
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
    }
}


`call.enqueue(new Callback<SearchRepoBean>() {})`最終調用的方法是OkhttpCall中的`call.enqueue(new okhttp3.Callback() {})`

```java

    final class OkHttpCall<T> implements Call<T> {

    //……
        @Override public void enqueue(final Callback<T> callback) {

    //……
            call.enqueue(new okhttp3.Callback() {
                @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
                Response<T> response;
                //……
                try {
                    callback.onResponse(OkHttpCall.this, response);
                } catch (Throwable t) {
                    t.printStackTrace();
                }
            }
        });
    }
//……
}

複製代碼
相關文章
相關標籤/搜索