Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

有多个BaseUrl 怎么处理 #27

Closed
LuoboDcom opened this issue Dec 28, 2016 · 26 comments
Closed

有多个BaseUrl 怎么处理 #27

LuoboDcom opened this issue Dec 28, 2016 · 26 comments

Comments

@LuoboDcom
Copy link

当有多个 baseUrl 时,怎么创建retrofit 好些呢? 看了架构源码,感觉不好处理。
还有个问题,没理解 Presenter 创建时,它依赖的对象是怎么创建的?希望指教下

@JessYanCoding
Copy link
Owner

JessYanCoding commented Dec 28, 2016

针对第一个问题,最近问我的人有点多,这个
是retrofit的限制,每个retrofit对象只能有一个baseurl,每次请求接口都拿这个baseurl去给okhttp去请求服务器,但是我已经有解决方法,最近在完善,可以follow我,第二个问题,无非就是dagger的使用,dagger一时半会讲不清楚,懂dagger的人,自然看的懂我写的,不懂的讲也听不懂,建议你还是自己去看看文章,这个框架用dagger的地方太多,不懂看源码老火

@GHdeng
Copy link

GHdeng commented Jan 3, 2017

完善了多个 baseUrl 吗

@JessYanCoding
Copy link
Owner

还在研究,@get@post可以传全路径,先使用这个替代,

@LuoboDcom
Copy link
Author

@JessYanCoding
Copy link
Owner

retrofit.create,会创建一个叫ServiceMethod的类,里面持有类型为httpurl的baseurl字段,每次请求他会调用ServiceMethod的toRequest方法,将baseurl,和relativeUrl结合为请求的url,封装到request对象里,因为持有的baseurl为对象,所以动态更换baseurl,不能实现同时请求两个baseurl不同的接口,但是重新创建其他配置信息一致,只是baseurl不一样的retrofit,太过于浪费资源,所以最好的解决办法就是@get或者@post传全路径,或者在参数中@url传全路径

@ghost
Copy link

ghost commented Jan 12, 2017

看到一个做法,利用反射。retrofit 创建的时候,用反射获取baseUrl 。baseUrl写到service里面。

@JessYanCoding
Copy link
Owner

使用反射将baseUrl写到ServiceMethod里?baseurl用final修饰的,我想的是通过javasisst将baseUrl添加到@get@post

@ghost
Copy link

ghost commented Jan 12, 2017

public class RetrofitFactory {

    private final Gson mGson;

    public RetrofitFactory() {
        mGson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd hh:mm:ss")
                .create();
    }

    private static class SingleOnHolder {
        private static final RetrofitFactory INSTANCE = new RetrofitFactory();
    }

    public static RetrofitFactory getInstance() {
        return SingleOnHolder.INSTANCE;
    }

    public <S> S createService(Class<S> serviceClass) {
        String baseUrl = "";
        try {
            Field field = serviceClass.getField("BASE_URL");
            try {
                baseUrl = (String) field.get(field);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(getOkHttp())
                .addConverterFactory(GsonConverterFactory.create(mGson))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        return retrofit.create(serviceClass);
    }

    private final static long DEFAULT_TIMEOUT = 10;

    private OkHttpClient getOkHttp() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Log.i("OkHttp", message);
            }
        });
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder okhttp = new OkHttpClient.Builder();
        okhttp.addInterceptor(interceptor);
        okhttp.addNetworkInterceptor(new CacheInterceptor());
        okhttp.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        okhttp.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        okhttp.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        okhttp.cache(new Cache(new File(Constant.CACHE), 10 * 1024 * 1024));
        return okhttp.build();
    }
}


public interface GankService {

    String BASE_URL = "http://gank.io/";

    @GET("api/data/{type}/{size}/{page}")
    Observable<GankDataBean> getGankData(@Path("type") String type, @Path("size") int size, @Path("page") int page);
}

使用的话,大概就是

RetrofitFactory.getInstance().createService(GankService.class).getGankData(xxxx);

@JessYanCoding
Copy link
Owner

感谢分享,我研究下

@JessYanCoding
Copy link
Owner

醉了,你这个还是创建了多个retrofit ,我要解决的是,一个retrofit 实现多个baseurl

@yubaokang
Copy link

@get("http://xxxxxxxx/api/data/{type}/{size}/{page}")
会覆盖baseUrl的,只要在某些特殊的url前面加上就会覆盖baseUrl的

@JessYanCoding
Copy link
Owner

我知道,这个我上面已经提到可以在@get,@post 加上全路径

@JessYanCoding
Copy link
Owner

我要实现的效果和上面的代码差不多,给每个interface加上一个注解,注解里面有baseurl,从而实现这个interface 的每个方法都使用这个baseurl ,而其他地方都不用改,也不用重复创建retrofit , 不加上这个注解就使用retrofit 默认的baseurl,这样一个注解就解决所有问题
解决思路之前就有了,通过AOP的思想,使用javasisst 更改字节码实现,可行性很高,只是最近年底事多,没时间实现

@ghost
Copy link

ghost commented Jan 13, 2017

Soga ,没想那么深入呢……所以这是要retrofit 变成单例?

@ghost
Copy link

ghost commented Jan 17, 2017

感觉不如给retrofit提个issue

@jamesliao333
Copy link

多个url,我觉得还是做成多个retrofit比较好。这样接口和业务更清晰

@JessYanCoding
Copy link
Owner

@jamesliao333 使接口和业务更清晰多划分几个API interface 就可以了, 但是创建几个其他配置一样只是baseurl 不一样的retrofit 对象,代价太大,retrofit 内部在每次请求网络接口时,也只是把初始化时配置的baseurl 和每个方法的@get中的url组合后作为请求地址

@jamesliao333
Copy link

@JessYanCoding 感谢作者的回复。但是感觉在@get @post里面加@url,如果是简单几个接口还可以这样解决。但遇到同等量级的几个请求服务器同时并存,每次在接口里面带入url,也不是非常好的解决方案哈。而且这样会使到网络请求代码更混乱,难以管理。再次感谢!

@JessYanCoding
Copy link
Owner

@jamesliao333 是的,就是挺不方便的,但是retrofit既然这样设计肯定有它考虑到的地方,所以我思考使用Aop能否实现

@xiaobailong24
Copy link
Collaborator

@JessYanCoding 加油啊,持续关注!

@cocowobo
Copy link

@JessYanCoding 老大,看上面都是过年的回复了,那你这现在解决这个问题了没有.坐等,急急急急,

@JessYanCoding
Copy link
Owner

@cocowobo 老铁,你没看我arms都更新了几个大版本了啊,现在工作又忙得很,理论方法去年就想好了,要想实现还需要些时间哦

@cocowobo
Copy link

cocowobo commented May 2, 2017 via email

@JessYanCoding
Copy link
Owner

@cocowobo 其实着都不是叫bug,Retrofit可能故意这样设计的,可以在每个接口动态传全路径,也可以根据不同的baseurl,new多个Retrofit,这些都是可以马上解决这个问题的,我只是觉得这些都并不完美,想用Aop的方式优雅的解决的,但是由于各方面原因以及时间的问题,所以有理论但是也没实践

@JessYanCoding
Copy link
Owner

@cocowobo @jamesliao333 https://github.com/JessYanCoding/RetrofitUrlManager 解决了仅使用一个 Retrofit 对象即可做到同时存在多个 BaseUrl ,并且每个 BaseUrl 都可以在 App 运行时动态切换为任意指定的 BaseUrl 且互不影响

@JessYanCoding
Copy link
Owner

解决方案的思路

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants