匕首 + 改装动态 URL
Dagger + Retrofit dynamic URL
问题
我需要从 USER 输入的域调用 API,并且我需要在调用之前根据插入的数据编辑我的 Retrofit
单例。
有没有办法"reset"我的单身人士,强迫它重建?
或
有没有办法在调用之前用我的数据(可能在拦截器中?)更新我的 baseUrl
?
代码
单身人士
@Provides
@Singleton
Retrofit provideRetrofit(SharedPreferences prefs) {
String apiUrl = "https://%1s%2s";
apiUrl = String.format(apiUrl, prefs.getString(ACCOUNT_SUBDOMAIN, null), prefs.getString(ACCOUNT_DOMAIN, null));
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new HeaderInterceptor())
.build();
return new Retrofit.Builder()
.baseUrl(apiUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
@Provides
@Singleton
API provideAPI(Retrofit retrofit) {
return retrofit.create(API.class);
}
API
@FormUrlEncoded
@POST("endpoint")
Observable<Response> logIn(@Field("login") String login, @Field("password") String password);
现在如何运作
好吧,我们的想法是在 API 调用之前通过 SharedPrefs
保存用户域数据,并使用格式化字符串修改 baseUrl
。
您可以实施 BaseUrl
并传递它而不是固定的 URL。check out this link
其他方法是实现 Endpoint
并利用 setUrl()
。因此,为了在 运行 时更改一些 header 值,您可以使用拦截器并将其添加到 OkHttp。
我在这里看到 2 个选项:
- 按预期使用匕首。为每个
baseUrl
创建自己的 Retrofit
客户,或
- 在发送之前使用拦截器修改请求
匕首逼近
如果你要暴力破解 urls,这可能不是正确的选择,因为它依赖于为每个创建一个新的 Retrofit
实例。
现在,每次 url 更改时,您只需重新创建以下演示的 UrlComponent
,方法是为其提供新的 UrlModule
。
清理
清理您的 @Singleton
模块,以便它提供 GsonConverterFactory
和 RxJavaCallAdapterFactory
以正确使用 dagger 而不是重新创建共享对象。
@Module
public class SingletonModule {
@Provides
@Singleton
GsonConverterFactory provideOkHttpClient() {/**/}
@Provides
@Singleton
RxJavaCallAdapterFactory provideOkHttpClient() {/**/}
}
@Singleton
@Component(modules = SingletonModule.class)
interface SingletonComponent {
// sub component
UrlComponent plus(UrlModule component);
}
Url 范围
引入 @UrlScope
来限定您的 Retrofit
个实例。
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface UrlScope {
}
然后创建子组件
@SubComponent(modules=UrlModule.class)
public interface UrlComponent {}
还有一个模块
@Module
class UrlModule {
private final String mUrl;
UrlModule(String url) { mUrl = url; }
@Provides
String provideUrl() {
return mUrl;
}
@Provides
@UrlScope
OkHttpClient provideOkHttpClient(String url) {
return new OkHttpClient.Builder().build();
}
@Provides
@UrlScope
Retrofit provideRetrofit(OkHttpClient client) {
return new Retrofit.Builder().build();
}
}
使用范围 Retrofit
实例化组件并使用它。
class Dagger {
public void demo() {
UrlModule module = new UrlModule(/*some url*/);
SingletonComponent singletonComponent = DaggerSingletonComponent.create();
UrlComponent urlComponent = singletonComponent.plus(module);
urlComponent.getRetrofit(); // done.
}
}
OkHttp 方法
提供一个适当范围的拦截器(@Singleton
在这种情况下)并实现相应的逻辑。
@Module
class SingletonModule {
@Provides
@Singleton
GsonConverterFactory provideGsonConverter() { /**/ }
@Provides
@Singleton
RxJavaCallAdapterFactory provideRxJavaCallAdapter() { /**/ }
@Provides
@Singleton
MyApiInterceptor provideMyApiInterceptor() { /**/ }
@Provides
@Singleton
OkHttpClient provideOkHttpClient(MyApiInterceptor interceptor) {
return new OkHttpClient.Builder().build();
}
@Provides
@Singleton
Retrofit provideRetrofit(OkHttpClient client) {
return new Retrofit.Builder().build();
}
}
@Singleton
@Component(modules = SingletonModule.class)
interface SingletonComponent {
Retrofit getRetrofit();
MyApiInterceptor getInterceptor();
}
todo 实施 MyApiInterceptor
。您需要为基础url设置一个setter,然后重写/修改通过的请求。
然后,再一次,继续使用它。
class Dagger {
public void demo() {
SingletonComponent singletonComponent = DaggerSingletonComponent.create();
MyService service = singletonComponent.getRetrofit().create(MyService.class);
MyApiInterceptor interceptor = singletonComponent.getInterceptor();
interceptor.setBaseUrl(myUrlA);
service.doA();
interceptor.setBaseUrl(someOtherUrl);
service.doB();
}
}
作为第三种方法,您还可以使用 反射 直接更改基数 URL——我最后添加这个只是为了完整性。
问题
我需要从 USER 输入的域调用 API,并且我需要在调用之前根据插入的数据编辑我的 Retrofit
单例。
有没有办法"reset"我的单身人士,强迫它重建?
或
有没有办法在调用之前用我的数据(可能在拦截器中?)更新我的 baseUrl
?
代码
单身人士
@Provides
@Singleton
Retrofit provideRetrofit(SharedPreferences prefs) {
String apiUrl = "https://%1s%2s";
apiUrl = String.format(apiUrl, prefs.getString(ACCOUNT_SUBDOMAIN, null), prefs.getString(ACCOUNT_DOMAIN, null));
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new HeaderInterceptor())
.build();
return new Retrofit.Builder()
.baseUrl(apiUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
@Provides
@Singleton
API provideAPI(Retrofit retrofit) {
return retrofit.create(API.class);
}
API
@FormUrlEncoded
@POST("endpoint")
Observable<Response> logIn(@Field("login") String login, @Field("password") String password);
现在如何运作
好吧,我们的想法是在 API 调用之前通过 SharedPrefs
保存用户域数据,并使用格式化字符串修改 baseUrl
。
您可以实施 BaseUrl
并传递它而不是固定的 URL。check out this link
其他方法是实现 Endpoint
并利用 setUrl()
。因此,为了在 运行 时更改一些 header 值,您可以使用拦截器并将其添加到 OkHttp。
我在这里看到 2 个选项:
- 按预期使用匕首。为每个
baseUrl
创建自己的Retrofit
客户,或 - 在发送之前使用拦截器修改请求
匕首逼近
如果你要暴力破解 urls,这可能不是正确的选择,因为它依赖于为每个创建一个新的 Retrofit
实例。
现在,每次 url 更改时,您只需重新创建以下演示的 UrlComponent
,方法是为其提供新的 UrlModule
。
清理
清理您的 @Singleton
模块,以便它提供 GsonConverterFactory
和 RxJavaCallAdapterFactory
以正确使用 dagger 而不是重新创建共享对象。
@Module
public class SingletonModule {
@Provides
@Singleton
GsonConverterFactory provideOkHttpClient() {/**/}
@Provides
@Singleton
RxJavaCallAdapterFactory provideOkHttpClient() {/**/}
}
@Singleton
@Component(modules = SingletonModule.class)
interface SingletonComponent {
// sub component
UrlComponent plus(UrlModule component);
}
Url 范围
引入 @UrlScope
来限定您的 Retrofit
个实例。
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface UrlScope {
}
然后创建子组件
@SubComponent(modules=UrlModule.class)
public interface UrlComponent {}
还有一个模块
@Module
class UrlModule {
private final String mUrl;
UrlModule(String url) { mUrl = url; }
@Provides
String provideUrl() {
return mUrl;
}
@Provides
@UrlScope
OkHttpClient provideOkHttpClient(String url) {
return new OkHttpClient.Builder().build();
}
@Provides
@UrlScope
Retrofit provideRetrofit(OkHttpClient client) {
return new Retrofit.Builder().build();
}
}
使用范围 Retrofit
实例化组件并使用它。
class Dagger {
public void demo() {
UrlModule module = new UrlModule(/*some url*/);
SingletonComponent singletonComponent = DaggerSingletonComponent.create();
UrlComponent urlComponent = singletonComponent.plus(module);
urlComponent.getRetrofit(); // done.
}
}
OkHttp 方法
提供一个适当范围的拦截器(@Singleton
在这种情况下)并实现相应的逻辑。
@Module
class SingletonModule {
@Provides
@Singleton
GsonConverterFactory provideGsonConverter() { /**/ }
@Provides
@Singleton
RxJavaCallAdapterFactory provideRxJavaCallAdapter() { /**/ }
@Provides
@Singleton
MyApiInterceptor provideMyApiInterceptor() { /**/ }
@Provides
@Singleton
OkHttpClient provideOkHttpClient(MyApiInterceptor interceptor) {
return new OkHttpClient.Builder().build();
}
@Provides
@Singleton
Retrofit provideRetrofit(OkHttpClient client) {
return new Retrofit.Builder().build();
}
}
@Singleton
@Component(modules = SingletonModule.class)
interface SingletonComponent {
Retrofit getRetrofit();
MyApiInterceptor getInterceptor();
}
todo 实施 MyApiInterceptor
。您需要为基础url设置一个setter,然后重写/修改通过的请求。
然后,再一次,继续使用它。
class Dagger {
public void demo() {
SingletonComponent singletonComponent = DaggerSingletonComponent.create();
MyService service = singletonComponent.getRetrofit().create(MyService.class);
MyApiInterceptor interceptor = singletonComponent.getInterceptor();
interceptor.setBaseUrl(myUrlA);
service.doA();
interceptor.setBaseUrl(someOtherUrl);
service.doB();
}
}
作为第三种方法,您还可以使用 反射 直接更改基数 URL——我最后添加这个只是为了完整性。