手寫Retrofit Get請求(支持Rxjava)

Retrofit2 簡單介紹

簡單的說就是一個網(wǎng)絡(luò)請求的適配器剃幌,它將一個基本的Java接口通過動態(tài)代理的方式翻譯成一個HTTP請求琴许,并通過OkHttp去發(fā)送請求税肪。更具體自行搜索

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

手寫調(diào)用

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

創(chuàng)建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 "";
}

創(chuàng)建Retrofit 通過Builder 初始化參數(shù)

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) {
            //緩存沒有取到 創(chuàng)建ServiceMethod 并緩存
            serviceMethod = new ServiceMethod.Builder(this, method).build();
            serviceMethodCache.put(method, serviceMethod);
        }
        return serviceMethod;

    }


    /**
     * 構(gòu)建著模式
     */
    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);創(chuàng)建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) {
        //創(chuàng)建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() {
            //處理參數(shù)
            mParameterHandler = new ParameterHandler[mParameterAnnotations.length];
            for (int i = 0; i < mParameterAnnotations.length; i++) {
                Annotation[] parameterAnnotation = mParameterAnnotations[i];
                //遍歷一個參數(shù)上的所有注解
                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();
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末净捅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子辩块,更是在濱河造成了極大的恐慌蛔六,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件废亭,死亡現(xiàn)場離奇詭異国章,居然都是意外死亡,警方通過查閱死者的電腦和手機豆村,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門液兽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掌动,你說我怎么就攤上這事四啰。” “怎么了坏匪?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵拟逮,是天一觀的道長。 經(jīng)常有香客問我适滓,道長,這世上最難降的妖魔是什么恋追? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任凭迹,我火速辦了婚禮罚屋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嗅绸。我一直安慰自己脾猛,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布鱼鸠。 她就那樣靜靜地躺著猛拴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚀狰。 梳的紋絲不亂的頭發(fā)上愉昆,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音麻蹋,去河邊找鬼跛溉。 笑死,一個胖子當著我的面吹牛扮授,可吹牛的內(nèi)容都是我干的芳室。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼刹勃,長吁一口氣:“原來是場噩夢啊……” “哼堪侯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起荔仁,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤抖格,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后咕晋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雹拄,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年掌呜,在試婚紗的時候發(fā)現(xiàn)自己被綠了滓玖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡质蕉,死狀恐怖势篡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情模暗,我是刑警寧澤禁悠,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站兑宇,受9級特大地震影響碍侦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一瓷产、第九天 我趴在偏房一處隱蔽的房頂上張望站玄。 院中可真熱鬧,春花似錦濒旦、人聲如沸株旷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晾剖。三九已至,卻和暖如春梯嗽,著一層夾襖步出監(jiān)牢的瞬間齿尽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工慷荔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雕什,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓显晶,卻偏偏與公主長得像贷岸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子磷雇,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容