gpt4 book ai didi

java - 如何将依赖项注入(inject)到需要前一个 Activity 参数的 Activity 中?

转载 作者:行者123 更新时间:2023-12-02 11:23:43 26 4
gpt4 key购买 nike

我有一个 LoginActivity,用户通过 Auth0 登录并返回一个身份验证 token 。该 token 被传递到 MainActivity:

Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra(KEY_ACCESS_TOKEN, credentials.getAccessToken());
intent.putExtra(KEY_ID_TOKEN, credentials.getIdToken());
startActivity(intent);

我能够通过 following this guide 很好地使用 LoginActivity 进行依赖注入(inject).

现在我正在尝试将依赖项注入(inject)到 MainActivity 中。我的 MainActivity 有一个 MainActivityViewModel 来处理 UI 和数据层之间的所有交互。我想将我的 API 注入(inject)到我的 ViewModel 中:

PetshackApi apiService;

@Inject
public PetMapViewModel(PetshackApi apiService) {
this.apiService = apiService;
}

我定义了 ViewModelModuleViewModelKeyMainActivityViewModelFactory(从 GithubViewModelFactory 重命名)。我在 MainActivity 的顶部注入(inject)了 viewModelFactory:

@Inject
ViewModelProvider.Factory viewModelFactory;

然后使用工厂来获取我的viewModel:

viewModel = ViewModelProviders.of(this, viewModelFactory).get(MainActivityViewModel.class);

我使用this answer进行设置.

问题是我的 Retrofit/PetshackApi 依赖项将需要 LoginActivity 中的 accessToken。因此,我在 MainActivity 中定义了另一个方法来允许检索它:

public String getAccessToken() {
return getIntent().getStringExtra(LoginActivity.KEY_ACCESS_TOKEN);
}

我在设置模块/组件/时遇到问题???。我想我需要以某种方式将 MainActivity 注入(inject)到我的模块中,所以我尝试遵循 Injecting Activity objects .

MainActivityComponent.java

@Component(modules={AndroidSupportInjectionModule.class, AppModule.class, MainActivityModule.class, ViewModelModule.class})
public interface MainActivityComponent extends AndroidInjector<PetApplication> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<PetApplication>{
@BindsInstance
abstract Builder application(Application application);
}
void inject(MainActivity mainActivity);
}

MainActivityModule.java

@Module(subcomponents = MainActivitySubcomponent.class)
abstract class MainActivityModule {
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity>
bindMainActivityInjectorFactory(MainActivitySubcomponent.Builder builder);
}

MainActivitySubcomponent.java

@Subcomponent(modules = MainActivityChildModule.class)
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
@Subcomponent.Builder
public abstract class Builder extends AndroidInjector.Builder<MainActivity> {}
}

MainActivityChildModule.java

@Module
abstract class MainActivityChildModule {
@Provides
@Singleton
Retrofit providesRetrofit(Application application, MainActivity mainActivity) {
final String accessToken = mainActivity.getAccessToken();
Interceptor interceptor = new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("authorization", "Bearer " + accessToken).build();
return chain.proceed(newRequest);
}
};

// Add the interceptor to OkHttpClient
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.interceptors().add(interceptor);
OkHttpClient client = builder.build();

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(application.getString(R.string.endpoint_url))
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}

@Provides
@Singleton // needs to be consistent with the component scope
PetshackApi providesPetshackApiInterface(Retrofit retrofit) {
return retrofit.create(PetshackApi.class);
}
}

我走在正确的道路上吗?有关如何执行此操作的任何提示或示例?

最佳答案

我建议将网络代码移到“Activity ”模块之外,并创建一个可以在应用程序之间共享的应用程序模块。

重要的是,如果您有一个 TokenStore 为每个请求提供 token ,您需要在发送请求时更新该值。

@Module
abstract class NetworkModule {

@Provides
@Singleton
static TokenStore provideTokenStore(TokenStoreImpl tokenStore) {
return tokenStore;
}

@Provides
@Singleton
static OkHttpClient provideOkHttpClient(AuthInterceptor authInterceptor) {
// Add the interceptor to OkHttpClient
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.interceptors().add(authInterceptor);
return builder.build();
}

@Provides
@Singleton
static Retrofit providesRetrofit(Application application, OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(application.getString(R.string.endpoint_url))
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
return retrofit;
}

@Provides
@Singleton // needs to be consistent with the component scope
static PetshackApi providesPetshackApiInterface(Retrofit retrofit) {
return retrofit.create(PetshackApi.class);
}
}

interface TokenStore {
String getToken();
void setToken(String token);
}

@Singleton
class TokenStoreImpl implements TokenStore {

String token;

@Inject
public TokenStoreImpl() { }

@Override
public String getToken() {
return token;
}

@Override
public void setToken(String token) {
this.token = token;
}
}

@Singleton
class AuthInterceptor implements Interceptor {

private final TokenStore tokenStore;

@Inject
public AuthInterceptor(TokenStore tokenStore) {
this.tokenStore = tokenStore;
}

@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request()
.newBuilder().addHeader("authorization", "Bearer " + tokenStore.getToken()).build();
return chain.proceed(newRequest);
}
}

关于java - 如何将依赖项注入(inject)到需要前一个 Activity 参数的 Activity 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49743715/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com