问题
我需要从USER输入的域调用API,我需要在调用之前编辑我的Retrofit
单例,这与插入的数据有关。
有没有办法重置"我的单身人士,强迫它重新创造?
或
有没有办法在调用之前用我的数据(可能是Interceptor?)更新我的baseUrl
?
CODE
单身
@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
保存用户域数据,并使用格式化的String修改baseUrl
。
答案 0 :(得分:10)
我在这里看到两个选项:
baseUrl
个Retrofit
客户端或如果您使用暴力网址,这可能不是正确的选择,因为它依赖于为每个网址创建一个新的Retrofit
实例。
现在,每当网址发生变化时,您只需通过向其提供新的UrlComponent
来重新创建以下所示的UrlModule
。
清理您的@Singleton
模块,以便它提供GsonConverterFactory
和RxJavaCallAdapterFactory
以正确使用匕首,而不是重新创建共享对象。
@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);
}
引入@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.
}
}
提供适当范围的拦截器(在这种情况下为@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
。您需要为基本网址设置 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();
}
}
作为第三种方法,您还可以使用 reflection 直接更改基本URL - 我为了完整性而添加了最后一个。
答案 1 :(得分:5)
您可以实施<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">WebSiteName</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Home</a>
</li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Page 1 <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Page 1-1</a>
</li>
<li><a href="#">Page 1-2</a>
</li>
<li><a href="#">Page 1-3</a>
</li>
</ul>
</li>
<li><a href="#">Page 2</a>
</li>
<li><a href="#"><span class="glyphicon glyphicon-user"></span> Sign Up</a>
</li>
<li><a href="#"><span class="glyphicon glyphicon-log-in"></span> Login</a>
</li>
</ul>
</div>
</nav>
并传递该内容而不是固定网址。check out this link
其他方法是实现BaseUrl
并使用Endpoint
。因此,为了在运行时更改某些标头值,您可以使用拦截器并将其添加到OkHttp。