手写Retrofit Get请求(支持Rxjava)

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();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容