美文网首页
手写Retrofit Get请求(支持Rxjava)

手写Retrofit Get请求(支持Rxjava)

作者: 小熊_c37d | 来源:发表于2018-11-20 11:09 被阅读0次

    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();
        }
    }
    

    相关文章

      网友评论

          本文标题:手写Retrofit Get请求(支持Rxjava)

          本文链接:https://www.haomeiwen.com/subject/nretqqtx.html