开发中会遇到URL需要动态切换,若你还是通过gradle打包切换是否不太灵活,下面将介绍一下retrofit基于OKhttp中动态修改URL;
原理添加拦截器,在retrofit中的现实更加灵活了如下代码:
private RetrofitUrlManager() { if (!DEPENDENCY_OKHTTP) { //使用本框架必须依赖 Okhttp throw new IllegalStateException("Must be dependency Okhttp"); } UrlParser urlParser = new DefaultUrlParser(); urlParser.init(this); setUrlParser(urlParser); this.mInterceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { if (!isRun()) // 可以在 App 运行时, 随时通过 setRun(false) 来结束本框架的运行 return chain.proceed(chain.request()); return chain.proceed(processRequest(chain.request())); } }; }
下面是对retrofit设置的URL解析及添加到拦截器中
/** * 对 {@link Request} 进行一些必要的加工, 执行切换 BaseUrl 的相关逻辑 * * @param request {@link Request} * @return {@link Request} */ public Request processRequest(Request request) { if (request == null) return request; Request.Builder newBuilder = request.newBuilder(); String url = request.url().toString(); //如果 Url 地址中包含 IDENTIFICATION_IGNORE 标识符, 框架将不会对此 Url 进行任何切换 BaseUrl 的操作 if (url.contains(IDENTIFICATION_IGNORE)) { return pruneIdentification(newBuilder, url); } String domainName = obtainDomainNameFromHeaders(request); HttpUrl httpUrl; Object[] listeners = listenersToArray(); // 如果有 header,获取 header 中 domainName 所映射的 url,若没有,则检查全局的 BaseUrl,未找到则为null if (!TextUtils.isEmpty(domainName)) { notifyListener(request, domainName, listeners); httpUrl = fetchDomain(domainName); newBuilder.removeHeader(DOMAIN_NAME); } else { notifyListener(request, GLOBAL_DOMAIN_NAME, listeners); httpUrl = getGlobalDomain(); } if (null != httpUrl) { HttpUrl newUrl = mUrlParser.parseUrl(httpUrl, request.url()); if (debug) Log.d(RetrofitUrlManager.TAG, "The new url is { " + newUrl.toString() + " }, old url is { " + request.url().toString() + " }"); if (listeners != null) { for (int i = 0; i < listeners.length; i++) { ((onUrlChangeListener) listeners[i]).onUrlChanged(newUrl, request.url()); // 通知监听器此 Url 的 BaseUrl 已被切换 } } return newBuilder .url(newUrl) .build(); } return newBuilder.build(); }
具体的使用,在retrofitAPI接口中添加@Headers({"Domain-Name: CONTROL"}) Domain-Name是key,CONTROL 设置的URL对应的key名称
/** * ----------------------- * @author: qiuxianfu * @date: 2021/1/27 * ----------------------- */ public interface PerformanceApi { @Headers({"Domain-Name: CONTROL"}) @POST("xxx/xxx/getSiteAreaPlanning") Observable<PerformancesResponse> getDataList(@Query("userCode") String userCode); @Headers({"Domain-Name: CONTROL"}) @POST("xxx/xxx/addDutyRoster") Observable<AddDutyTosterResponse> addDutyRoster(@Body AddDutyRosterRequest rosterRequest); }
这里就是动态设置了,CONTROL这个和@Headers({"Domain-Name: CONTROL"}) 保持一致
RetrofitUrlManager.getInstance().putDomain("CONTROL", InfieldAppUtils.getServerControlHttp()); }