手写Retrofit Get请求(支持Rxjava)
2018-11-20 本文已影响0人
小熊_c37d
Retrofit2 简单介绍
简单的说就是一个网络请求的适配器,它将一个基本的Java接口通过动态代理的方式翻译成一个HTTP请求,并通过OkHttp去发送请求。更具体自行搜索
public void getWeather() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.apiopen.top/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
Weather weather = retrofit.create(Weather.class);
Call<WeatherData> call = weather.getWeather("杭州");
call.enqueue(new Callback<WeatherData>() {
@Override
public void onResponse(Call<WeatherData> call, Response<WeatherData> response) {
Log.i(TAG, "onResponse: " + new Gson().toJson(response.body()));
}
@Override
public void onFailure(Call<WeatherData> call, Throwable t) {
}
});
}
interface Weather {
@GET("weatherApi")
Call<WeatherData> getWeather(@Query("city") String string);
}
手写调用
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.apiopen.top/").callAdapter(new RxJava2CallAdapterFactory()).build();
Weather weather = retrofit.create(Weather.class);
Observable<WeatherData> call = weather.getWeather("杭州");
call.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<WeatherData>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(WeatherData data) {
Log.i(TAG, "onNext: " + data.getData().getCity());
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
Call<WeatherData> dataCall = weather.getWeather1("南京");
dataCall.enqueue(new Callback<WeatherData>() {
@Override
public void onResponse(Call<WeatherData> call, IResponse<WeatherData> response) {
WeatherData.DataBean data = response.body.getData();
Log.i(TAG, "onResponse: " + data.getCity());
}
//
@Override
public void onFailure(Call<WeatherData> call, Throwable t) {
}
});
}
interface Weather {
@GET("weatherApi")
Observable<WeatherData> getWeather(@Query("city") String string);
@GET("weatherApi")
Call<WeatherData> getWeather1(@Query("city") String string);
}
创建Get请求需要的注解 Get ,Query
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GET {
String value();
}
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Query {
String value() default "";
}
创建Retrofit 通过Builder 初始化参数
public class Retrofit {
private HttpUrl baseUrl;
private okhttp3.Call.Factory callFactroy;
private ConcurrentHashMap<Method, ServiceMethod> serviceMethodCache;
private CallAdapter.Factory callAdapter;
public Retrofit(Builder builder) {
serviceMethodCache = new ConcurrentHashMap<>();
baseUrl = builder.baseUrl;
callFactroy = builder.callFactroy;
callAdapter = builder.callAdapter;
}
public HttpUrl getBaseUrl() {
return baseUrl;
}
public okhttp3.Call.Factory callFactroy() {
return callFactroy;
}
public CallAdapter.Factory callAdapter() {
return callAdapter;
}
public <T> T create(final Class<?> service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
//缓存查找ServiceMethod
private ServiceMethod loadServiceMethod(Method method) {
//从缓存里获取
ServiceMethod serviceMethod = serviceMethodCache.get(method);
if (null == serviceMethod) {
//缓存没有取到 创建ServiceMethod 并缓存
serviceMethod = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, serviceMethod);
}
return serviceMethod;
}
/**
* 构建着模式
*/
public static final class Builder {
private HttpUrl baseUrl;
private okhttp3.Call.Factory callFactroy;
private CallAdapter.Factory callAdapter;
public Builder baseUrl(String baseUrl) {
this.baseUrl = HttpUrl.parse(baseUrl);
return this;
}
public Builder callFactroy(okhttp3.Call.Factory callFactroy) {
this.callFactroy = callFactroy;
return this;
}
public Builder callAdapter(CallAdapter.Factory factory) {
this.callAdapter = factory;
return this;
}
public Retrofit build() {
if (null == baseUrl) {
throw new IllegalArgumentException("HttpUrl not set");
}
if (null == callFactroy) {
callFactroy = new OkHttpClient();
}
return new Retrofit(this);
}
}
}
Weather weather = retrofit.create(Weather.class); 我们可以看到这里通过Proxy.newProxyInstance 代理了这个接口,里面做了三件事情 loadServiceMethod(method);缓存查找 loadServiceMethod(method);创建OkHttpCall ,serviceMethod.adapt(okHttpCall)拿到需要的call
public <T> T create(final Class<?> service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
ServiceMethod
public class ServiceMethod<R, T> {
//请求类型 POST GET
private String httpMethod;
//请求的地址 不包含baseUrl;
private String mRelativeUrl;
private ParameterHandler[] mParameterHandler;
private final Retrofit mRetrofit;
private HttpUrl.Builder mUrlBuilder;
private final okhttp3.Call.Factory mCallFactroy;
private FormBody.Builder mFormBody;
private RequestBody mRequestBody;
private Method mMethod;
private CallAdapter<R, T> callAdapter;
public ServiceMethod(Builder builder) {
mMethod = builder.mMethod;
mRetrofit = builder.mRetrofit;
httpMethod = builder.httpMethod;
mRelativeUrl = builder.mRelativeUrl;
mParameterHandler = builder.mParameterHandler;
mCallFactroy = mRetrofit.callFactroy();
callAdapter = (CallAdapter<R, T>) mRetrofit.callAdapter().get();
}
public Method getMethod() {
return mMethod;
}
public Call toCall(Object[] args) {
//创建Okhttp Request
Request.Builder requestBuilder = new Request.Builder();
//确定地址请求地址
if (mUrlBuilder == null) {
mUrlBuilder = mRetrofit.getBaseUrl().newBuilder(mRelativeUrl);
}
for (int i = 0; i < mParameterHandler.length; i++) {
mParameterHandler[i].appley(this, String.valueOf(args[i]));
}
requestBuilder.url(mUrlBuilder.build());
requestBuilder.method(httpMethod, null);
Request request = requestBuilder.build();
return mCallFactroy.newCall(request);
}
//get请求Query 注解
public void addQueryParameter(String name, String value) {
mUrlBuilder.addQueryParameter(name, value);
}
public T adapt(Call<T> call) {
Type genericReturnType = mMethod.getGenericReturnType();
Class<?> rawType = getRawType(genericReturnType);
//判断方法返回类型 是Call 直接用默认的callAdapter
if (rawType == Call.class) {
return (T) DefaultCallAdapterFactory.INSTANCE.get().adapt(call);
}
//使用传入的RxJava2CallAdapterFactory
return callAdapter.adapt(call);
}
Class<?> getRawType(Type type) {
checkNotNull(type, "type == null");
if (type instanceof Class<?>) {
// Type is a normal class.
return (Class<?>) type;
}
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
// I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
// suspects some pathological case related to nested classes exists.
Type rawType = parameterizedType.getRawType();
if (!(rawType instanceof Class)) throw new IllegalArgumentException();
return (Class<?>) rawType;
}
if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();
}
if (type instanceof TypeVariable) {
// We could use the variable's bounds, but that won't work if there are multiple. Having a raw
// type that's more general than necessary is okay.
return Object.class;
}
if (type instanceof WildcardType) {
return getRawType(((WildcardType) type).getUpperBounds()[0]);
}
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
}
public static final class Builder {
private final Annotation[] mMethodAnnotations;
private final Annotation[][] mParameterAnnotations;
private final Retrofit mRetrofit;
//请求类型 POST GET
private String httpMethod;
//请求的地址 不包含baseUrl;
private String mRelativeUrl;
private ParameterHandler[] mParameterHandler;
private Method mMethod;
public Builder(Retrofit retrofit, Method method) {
mMethod = method;
mRetrofit = retrofit;
//拿到该方法注解
mMethodAnnotations = method.getAnnotations();
//拿到方法注解
mParameterAnnotations = method.getParameterAnnotations();
}
public ServiceMethod build() {
//处理方法注解
for (Annotation methodAnnotation : mMethodAnnotations) {
paresMethodAnnotation(methodAnnotation);
}
paresParameterAnnotation();
return new ServiceMethod(this);
}
private void paresMethodAnnotation(Annotation methodAnnotation) {
if (methodAnnotation instanceof GET) {
httpMethod = "GET";
GET get = (GET) methodAnnotation;
mRelativeUrl = get.value();
}
}
private void paresParameterAnnotation() {
//处理参数
mParameterHandler = new ParameterHandler[mParameterAnnotations.length];
for (int i = 0; i < mParameterAnnotations.length; i++) {
Annotation[] parameterAnnotation = mParameterAnnotations[i];
//遍历一个参数上的所有注解
for (Annotation annotation : parameterAnnotation) {
if (annotation instanceof Query) {
Query query = (Query) annotation;
String value = query.value();
mParameterHandler[i] = new ParameterHandler.Query(value);
}
}
}
}
}
}
ParameterHandler
public abstract class ParameterHandler {
abstract void appley(ServiceMethod method, String value);
static class Query extends ParameterHandler {
private final String mName;
public Query(String name) {
this.mName = name;
}
@Override
void appley(ServiceMethod method, String value) {
method.addQueryParameter(mName, value);
}
}
}
OkHttpCall
public class OkHttpCall<T> implements Call<T> {
final ServiceMethod serviceMethod;
final Object[] args;//自己传入的值
public OkHttpCall(ServiceMethod serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
@Override
public void enqueue(final Callback<T> callback) {
okhttp3.Call call = serviceMethod.toCall(args);
call.enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
if (callback != null) {
callback.onFailure(OkHttpCall.this, e);
}
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
IResponse rResponse = new IResponse();
rResponse.body = parseBody(response.body());
if (callback != null) {
callback.onResponse(OkHttpCall.this, rResponse);
}
}
});
}
@Override
public IResponse<T> execute() {
okhttp3.Call call = serviceMethod.toCall(args);
try {
IResponse objectResponse = new IResponse<>();
objectResponse.body=parseBody(call.execute().body());
return (IResponse<T>) objectResponse;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public <T> T parseBody(ResponseBody response) {
Type returnType = serviceMethod.getMethod().getGenericReturnType();
Class<T> dataClass = (Class<T>) ((ParameterizedType) returnType).getActualTypeArguments()[0];
Gson gson = new Gson();
T body = gson.fromJson(response.charStream(), dataClass);
return body;
}
}
Call
public interface Call<T> {
void enqueue(Callback<T> callback);
IResponse<T> execute();
}
CallAdapter
public interface CallAdapter<R, T> {
T adapt(Call<R> call);
abstract class Factory {
public abstract CallAdapter<?, ?> get();
}
}
Callback
public interface Callback<T> {
void onResponse(Call<T> call, IResponse<T> response);
void onFailure(Call<T> call, Throwable t);
}
public final class IResponse<T> {
public T body;
}
DefaultCallAdapterFactory 默认的callAdapter
public class DefaultCallAdapterFactory extends CallAdapter.Factory {
public static DefaultCallAdapterFactory INSTANCE = new DefaultCallAdapterFactory();
@Override
public CallAdapter get() {
return new CallAdapter<Object, Object>() {
@Override
public Object adapt(Call<Object> call) {
return call;
}
};
}
}
RxJava2CallAdapterFactory 支持rxjava的callAdapter
public class RxJava2CallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<?, ?> get() {
return new RxJava2CallAdapter();
}
}
public class RxJava2CallAdapter implements CallAdapter<Object,Object> {
@Override
public Object adapt(Call<Object> call) {
Observable<Object> responseObservable = new CallObservable<>(call);
return responseObservable;
}
}
final class CallObservable<T> extends Observable<T> {
private final Call<T> originalCall;
CallObservable(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
IResponse<T> response = originalCall.execute();
T body = response.body;
observer.onNext(body);
observer.onComplete();
}
}