使用PostMan進行請求測試 請求:https://api.github.com/search/repositories?q=android
html
返回值: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,
//……
},
//……
}
]
}
複製代碼
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
複製代碼
返回的報文采用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
//……
}
複製代碼
public interface GithubService {
//@Get註解,表示以Get方法發送網絡請求
//返回類型爲Call<SearchRepoBean>,SearchRepoBean是接收數據的類,能夠自定義
@GET("search/repositories")
Call<SearchRepoBean> getRepoInfo(@Query("q") String query);
}
複製代碼
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能夠經過爲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) {
//輸出結果
}
});
複製代碼
經過LiveDataCallAdapter
和LiveDataCallAdapterFactory
能夠將返回的數據表示爲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();
//輸出結果
}
});
複製代碼
.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;
}
}
}
複製代碼
.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);
}
}
}
複製代碼
.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;
}
//…………
}
複製代碼
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();
}
}
});
}
//……
}
複製代碼