为什么 Dagger 注入不起作用但 component.getObject 是
Why Dagger inject is not working but component.getObject yes
我正在尝试使用 Dagger 2 来实例化 Retrofit 接口。 CloudContactDataStore
class 注入 RestClient
并调用它的方法。
当我实例化一个 CloudContactDataStore
对象时,它的 RestClient
属性具有 null
值。
public class CloudContactDataStore implements ContactDataStore {
@Inject RestClient restClient;
public CloudContactDataStore() {
this.initializeInjector();
}
private void initializeInjector() {
ApiComponent component = DaggerApiComponent.builder()
.apiModule(new ApiModule())
.build();
component.inject(this); // Nothing changes, restClient is null!
this.restClient = component.getRestClient(); // This works
}
}
以下是我创建 Dagger 模块和组件的方法:
@Singleton
@Component(modules = ApiModule.class)
public interface ApiComponent {
void inject(ContactDataStore contactDataStore);
RestClient getRestClient();
}
@Module
public class ApiModule {
@Provides public RestClient provideRestClient(ApiService apiService) {
return new RestClientImpl(apiService);
}
@Provides public ApiService provideApiService(RestAdapter restAdapter) {
return restAdapter.create(ApiService.class);
}
@Provides public RestAdapter provideRestAdapter() {
return RestApiAdapter.getInstance();
}
}
那么,为什么 inject
函数不起作用,但调用 component
的 getRestClient()
是?
我发现查看 Dagger 2 生成的代码非常有用,因为它很容易理解,而且通常可以为您指明正确的方向。
Dagger 2 创建的代码与您编写的代码非常相似,因此请考虑如何实现 ApiComponent.inject(ContactDataStore)
。假设在该方法中您可以访问 RestClient,您将如何将其应用到现场?如果你坐下来写它,你会注意到你必须做这样的事情:
((CloudContactDataStore) contactDataStore).restClient = restClient;
或者换句话说,您需要将其转换为特定的实现。 Dagger 2 永远不会掉下来(至少我没见过),因为那通常是不安全的。
所以,你有两个选择。将 inject(ContactDataStore)
方法更改为 inject(CloudContactDataStore)
,或在 ContactDataStore
上提供允许传入 RestClient
的方法。
更新:无法通过抽象,即接口、方法进行@Inject。
如果你想通过 ContactDataStore
API 注入它,那么你有一个问题,因为目前 Dagger 2 中有一个限制(已提出删除它的功能请求),你不能用 @Inject
标记一个抽象方法。因此,与此同时(如果由于某些原因它无法在 Dagger 2 中工作,则永远如此)您将需要手动执行此操作,即从组件方法中获取 RestClient
的实例并将其传递给适当的方法在界面上。
我正在尝试使用 Dagger 2 来实例化 Retrofit 接口。 CloudContactDataStore
class 注入 RestClient
并调用它的方法。
当我实例化一个 CloudContactDataStore
对象时,它的 RestClient
属性具有 null
值。
public class CloudContactDataStore implements ContactDataStore {
@Inject RestClient restClient;
public CloudContactDataStore() {
this.initializeInjector();
}
private void initializeInjector() {
ApiComponent component = DaggerApiComponent.builder()
.apiModule(new ApiModule())
.build();
component.inject(this); // Nothing changes, restClient is null!
this.restClient = component.getRestClient(); // This works
}
}
以下是我创建 Dagger 模块和组件的方法:
@Singleton
@Component(modules = ApiModule.class)
public interface ApiComponent {
void inject(ContactDataStore contactDataStore);
RestClient getRestClient();
}
@Module
public class ApiModule {
@Provides public RestClient provideRestClient(ApiService apiService) {
return new RestClientImpl(apiService);
}
@Provides public ApiService provideApiService(RestAdapter restAdapter) {
return restAdapter.create(ApiService.class);
}
@Provides public RestAdapter provideRestAdapter() {
return RestApiAdapter.getInstance();
}
}
那么,为什么 inject
函数不起作用,但调用 component
的 getRestClient()
是?
我发现查看 Dagger 2 生成的代码非常有用,因为它很容易理解,而且通常可以为您指明正确的方向。
Dagger 2 创建的代码与您编写的代码非常相似,因此请考虑如何实现 ApiComponent.inject(ContactDataStore)
。假设在该方法中您可以访问 RestClient,您将如何将其应用到现场?如果你坐下来写它,你会注意到你必须做这样的事情:
((CloudContactDataStore) contactDataStore).restClient = restClient;
或者换句话说,您需要将其转换为特定的实现。 Dagger 2 永远不会掉下来(至少我没见过),因为那通常是不安全的。
所以,你有两个选择。将 inject(ContactDataStore)
方法更改为 inject(CloudContactDataStore)
,或在 ContactDataStore
上提供允许传入 RestClient
的方法。
更新:无法通过抽象,即接口、方法进行@Inject。
如果你想通过 ContactDataStore
API 注入它,那么你有一个问题,因为目前 Dagger 2 中有一个限制(已提出删除它的功能请求),你不能用 @Inject
标记一个抽象方法。因此,与此同时(如果由于某些原因它无法在 Dagger 2 中工作,则永远如此)您将需要手动执行此操作,即从组件方法中获取 RestClient
的实例并将其传递给适当的方法在界面上。