安卓进阶之 retrofit 动态切换URL地址

我们在开发的过程中,有时候会遇见需要动态切换URL的这种需求,借此记录一下。

首先贴出代码。

package com.example.administrator.mytestretrofit.http;

import android.util.Log;

import com.example.mylibrary.app.Constants;
import com.example.administrator.mytestretrofit.http.remote.RemoteService;
import com.example.mylibrary.http.engine.ExceptionEngine;
import com.example.mylibrary.http.engine.RetryWhenNetworkException;
import com.example.mylibrary.http.gson.IJson;
import com.example.mylibrary.http.interceptor.MoreBaseUrlInterceptor;
import com.example.mylibrary.http.subscriber.ProgressSubscriber;
import com.example.mylibrary.utils.log.LogUtils;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * http交互处理类
 */
public class HttpManager {

    public static final String TAG = "HttpManager-------";

    /*超时设置*/
    private static final int DEFAULT_TIMEOUT = 6;
    private RemoteService httpService;
    private volatile static HttpManager INSTANCE;

    //构造方法私有
    private HttpManager() {

        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                LogUtils.d(TAG,message);
            }
        });
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
                .connectTimeout(5, TimeUnit.SECONDS)  //设置超时时间 10s
                .readTimeout(5, TimeUnit.SECONDS)     //设置读取超时时间
                .writeTimeout(5, TimeUnit.SECONDS)   //设置写入超时时间
                .addInterceptor(httpLoggingInterceptor)//添加一个拦截器
                .addInterceptor(new MoreBaseUrlInterceptor());

        OkHttpClient okClient = builder.build();

        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(IJson.gson)) // 使用Gson作为数据转换器
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 使用RxJava作为回调适配器
                .client(okClient)
                .baseUrl(Constants.Base.BASE_URL_RELEASE)//获取 最终的base url
                /*.baseUrl(App.getInstance().getRealUrl())//此处选择 api 的真实网址*/
                .build();
        httpService = retrofit.create(RemoteService.class);
    }

    //获取单例
    public static HttpManager getInstance() {
        if (INSTANCE == null) {
            synchronized (HttpManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new HttpManager();
                }
            }
        }
        return INSTANCE;
    }

    /**
     * 处理http请求
     *
     * @param basePar 封装的请求数据
     */
    public void doHttpDeal(BaseEntity basePar) {
        //if (basePar.isShowProgress())
        ProgressSubscriber subscriber = new ProgressSubscriber(basePar.getListener()
                , basePar.getContext()
                , basePar.isShowProgress()
                , basePar.isCancel()
                , basePar.isShowError()
                , basePar.getMsg());
        basePar.getObservable(httpService)
                /*失败后的retry配置*/
                .retryWhen(new RetryWhenNetworkException())
                /*生命周期管理*/
                .compose(basePar.getTransformer())
//                .map(new_icon ServerResponseFunc<String>())//拦截服务器返回的错误
                .onErrorResumeNext(new HttpResponseFunc<String>()) //HttpResultFunc()为拦截onError事件的拦截器
                /*http请求线程*/
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                /*回调线程*/
                .observeOn(AndroidSchedulers.mainThread())
                /*结果判断*/
//                .map(basePar)
                .subscribe(subscriber);
    }

    private class HttpResponseFunc<T> implements Func1<Throwable, Observable<T>> {
        @Override
        public Observable<T> call(Throwable throwable) {
            Log.e(TAG,"----这是啥异常?--");
            throwable.printStackTrace();
            return Observable.error(ExceptionEngine.handleException(throwable)); //ExceptionEngine为处理异常的驱动器
        }
    }

}

 其中的关键在于这行代码的设置:.addInterceptor(new MoreBaseUrlInterceptor());

下面贴出这个类:

package com.example.mylibrary.http.interceptor;
import com.example.mylibrary.app.App;
import com.example.mylibrary.app.Constants;
import com.example.mylibrary.utils.cookie.UserUtils;

import java.io.IOException;
import java.util.List;

import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

public class MoreBaseUrlInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        //获取原始的originalRequest
        Request originalRequest = chain.request();
        //获取老的url
        HttpUrl oldUrl = originalRequest.url();
        //获取originalRequest的创建者builder
        Request.Builder builder = originalRequest.newBuilder();
        //获取头信息的集合如:manage,mdffx
        List<String> urlnameList = originalRequest.headers("urlname");
        if (urlnameList != null && urlnameList.size() > 0) {
            //删除原有配置中的值,就是namesAndValues集合里的值
            builder.removeHeader("urlname");
            //获取头信息中配置的value,如:manage或者mdffx
            String urlname = urlnameList.get(0);
            HttpUrl baseURL = null;
            //根据头信息中配置的value,来匹配新的base_url地址
            // FIXME: 2019/5/30 此处可以根据实际需求 进行 baseURL的切换
            if ("common_base_url_header".equals(urlname)) {
                baseURL = HttpUrl.parse(Constants.Base.BASE_URL_RELEASE);
            } else if ("old_php_base_url_header".equals(urlname)) {
                //baseURL = HttpUrl.parse(App.getInstance().setBaseUrlOldPhp());
            } else if ("java".equals(urlname)) {
                baseURL = HttpUrl.parse(Constants.Base.BASE_URL_RELEASE);
            }


            //重建新的HttpUrl,需要重新设置的url部分
            HttpUrl newHttpUrl = oldUrl.newBuilder()
                    .scheme(baseURL.scheme())//http协议如:http或者https
                    .host(baseURL.host())//主机地址
                    .port(baseURL.port())//端口
                    .build();
            String header = originalRequest.header("NoToken");
            if (header == null) {
                builder.addHeader("Cookie", UserUtils.getCokeValue())
                        .addHeader("Content-Type", "application/x-www-form-urlencoded")
                        .addHeader("X-Requested-With", "XMLHttpRequest");
            }

            //获取处理后的新newRequest
            Request newRequest = builder.url(newHttpUrl).build();
            return chain.proceed(newRequest);
        } else {
            return chain.proceed(originalRequest);
        }

    }
}

 代码的关键在于此处,根据不同的tag 对应不同的切换的URL地址。

此处可以贴出,网络请求的类,进行理解使用。

 根据上面设置的tag ,在remote类中,添加header 进行区分,亲测有效。

 此处为添加请求头,参数。大家可以根据自己的项目需求,灵活使用。

猜你喜欢

转载自blog.csdn.net/weixin_37166398/article/details/91802561