Android使用Dagger 2为动态更改URL实现HostSelectionInterceptor

时间:2017-08-05 08:25:14

标签: android retrofit retrofit2 dagger-2 dagger

我只是了解如何使用Dagger2实现Retrofit来设置动态更改网址reference

我尝试使用HostSelectionInterceptor类创建简单模块以在Dagger2上使用它,但我无法正确地做到这一点并且我得到错误:

我的NetworkModule

@Module(includes = ContextModule.class)
public class NetworkModule {
    @Provides
    @AlachiqApplicationScope
    public HttpLoggingInterceptor loggingInterceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Timber.e(message);
            }
        });
        interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
        return interceptor;
    }

    ...

    @Provides
    @AlachiqApplicationScope
    public HostSelectionInterceptor hostSelectionInterceptor() {
        return new HostSelectionInterceptor();
    }

    @Provides
    @AlachiqApplicationScope
    public OkHttpClient okHttpClient(HostSelectionInterceptor hostInterceptor, HttpLoggingInterceptor loggingInterceptor, Cache cache) {
        return new OkHttpClient.Builder()
                .addInterceptor(hostInterceptor)
                .addInterceptor(loggingInterceptor)
                .connectTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .cache(cache)
                .build();
    }
}

HostSelectionInterceptor模块:

@Module(includes = {NetworkModule.class})
public final class HostSelectionInterceptor implements Interceptor {
    private volatile String host;

    @Provides
    @AlachiqApplicationScope
    public String setHost(String host) {
        this.host = host;
        return this.host;
    }

    public String getHost() {
        return host;
    }

    @Provides
    @AlachiqApplicationScope
    @Override
    public okhttp3.Response intercept(Chain chain) {
        Request request = chain.request();
        String  host    = getHost();
        if (host != null) {
            HttpUrl newUrl = request.url().newBuilder()
                    .host(host)
                    .build();
            request = request.newBuilder()
                    .url(newUrl)
                    .build();
        }
        try {
            return chain.proceed(request);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

我现在收到此错误:

  

java.lang.IllegalArgumentException:意外主机:http://myUrl.com/ at okhttp3.HttpUrl $ Builder.host(HttpUrl.java:754)

问题是通过setHost方法在这行代码上设置主机:

HttpUrl newUrl = request.url().newBuilder()
        .host(host)
        .build();

2 个答案:

答案 0 :(得分:1)

基于this github comment,解决方案是替换

        HttpUrl newUrl = request.url().newBuilder()
                .host(host)
                .build();

        HttpUrl newUrl = HttpUrl.parse(host);

答案 1 :(得分:0)

你应该像这样使用拦截器:

class HostSelectionInterceptor: Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        apiHost?.let { host ->
            val request = chain.request()
            val newUrl = request.url.newBuilder().host(host).build()
            val newRequest = request.newBuilder().url(newUrl).build()
            return chain.proceed(newRequest)
        }
        throw IOException("Unknown Server")
    }
}

You just need to change at runtime the apiHost variable (var apiHost = "example.com"). Then add this interceptor to OkHttpClient builder:

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(HostSelectionInterceptor())
    .build()