【Android架構】基於MVP模式的Retrofit2+RXjava封裝之多Url(七)

歡子發表於2019-04-08

前言

最近好幾個朋友問我,多Url怎麼處理,這裡我們就說說這個。

套路一

Retrofit2是支援全路徑的,比如說

 @GET("http://api.csslcloud.net/api/room/create")
 Observable<String> createRoom(@Path("param") String param);
複製程式碼

所以,專案中只有個別介面需要的話,完全可以使用配置全路徑這種方式。

套路二

保留多個Retrofit物件 在之前的程式碼中,Retrofit一直是單例的,這裡我們可以建立2個Retrofit物件

  retrofit = new Retrofit.Builder()
                .baseUrl(BASE_SERVER_URL)
                .addConverterFactory(BaseConverterFactory.create())
                //支援RxJava2
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(client)
                .build();

        retrofit2 = new Retrofit.Builder()
                .baseUrl(BASE_SERVER_URL2)
                .addConverterFactory(BaseConverterFactory.create())
                //支援RxJava2
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(client)
                .build();

        apiServer = retrofit.create(ApiServer.class);

        apiServer2 = retrofit2.create(ApiServer.class);
複製程式碼

然後在使用時,區分

    /**
     * 獲取微分享列表
     */
    public void getShareList() {
        ...省略程式碼...
        ApiServer apiServer = ApiRetrofit2.getInstance().getApiService();
        ...省略程式碼...
    }

    /**
     * 獲取微分享列表
     */
    public void getShareList2() {
      ...省略程式碼...
        ApiServer apiServer = ApiRetrofit2.getInstance().getApiService2();
        ...省略程式碼...
    }
複製程式碼

當然這裡也就說說而已,估計沒人會這麼用...

套路三

JessYan 大神曾提過另外一種方案,原文地址

思路是,通過Okhttp的攔截器,動態改變介面的地址,那攔截器裡如何知道每個介面該使用哪個主地址呢? 這裡可以使用head,請求時,新增固定的標誌head,然後在攔截器中判斷,完成替換。

如何實現

首先,在ApiServer 中定義介面,新增head

    /**
     * 獲取分享列表
     *
     * @return
     */
    @FormUrlEncoded
    @POST("module/index.php?")
    @Headers({"url_mark:1"})
    Observable<List<ShareModel>> getShareList2(@FieldMap Map<String, String> map);

    /**
     * 獲取分享列表
     *
     * @return
     */
    @FormUrlEncoded
    @POST("module/index.php?")
    @Headers({"url_mark:2"})
    Observable<List<ShareModel>> getShareList3(@FieldMap Map<String, String> map);
複製程式碼

然後在Interceptor判斷head

    private Interceptor interceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            Log.e(TAG, "----------Request Start----------------");
            Log.e(TAG, "| OldUrl=" + request.url().toString());
            List<String> mark = request.headers("url_mark");

            HttpUrl newUrl = null;
            if (mark != null && mark.size() > 0) {
                Log.e(TAG, "| Head=" + mark.get(0));
                if (mark.get(0).equals("1")) {
                    newUrl = HttpUrl.parse("http://www.baidu.com/");
                } else if (mark.get(0).equals("2")) {
                    newUrl = HttpUrl.parse("http://www.github.com/");
                } else {
                    newUrl = request.url();
                }
                request = request.newBuilder().url(newUrl).build();
            }


            Log.e(TAG, "| NewUrl=" + request.url().toString());

            long startTime = System.currentTimeMillis();
            Response response = chain.proceed(request);
            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;
            MediaType mediaType = response.body().contentType();
            String content = response.body().string();


            Log.e(TAG, "| " + request.toString());
            Log.e(TAG, "| Response:" + content);
            Log.e(TAG, "----------Request End:" + duration + "毫秒----------");
            return response.newBuilder()
                    .body(ResponseBody.create(mediaType, content))
                    .build();
        }
    };
複製程式碼

結果如下:

image.png

當然,這裡是寫死的判斷,實際開發中,可能是提前知道或者介面返回具體哪些介面地址,可以存放在Map中,這裡直接取值就好。

最後,獻上原始碼 Github

參考 RetrofitUrlManager

RetrofitUrlManager 還提供了了更加豐富的替換規則,詳情可以檢視原始碼。

你的認可,是我堅持更新部落格的動力,如果覺得有用,就請點個贊,謝謝

相關文章