Why Dagger inject is not working but component.getObject yes

泪湿孤枕 提交于 2020-02-08 02:32:51

问题


I am trying to use Dagger 2 for instantiating a Retrofit interface. The CloudContactDataStore class injects the RestClient and calls its methods.

When I instantiate a CloudContactDataStore object, its RestClient attribute has null value.

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
    }
}

Here is how I create the Dagger Module and Component:

@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();
    }
}

So, why the inject function does not work but calling component's getRestClient() yes?


回答1:


I find it's very useful to look at the code that Dagger 2 generates as it's quite easy to follow and can often point you in the right direction.

Dagger 2 creates code much like you'd write so think about how you would implement ApiComponent.inject(ContactDataStore). Assuming within that method you had access to a RestClient how would you get it into the field? If you sat and wrote it you'd notice that you have to do something like this:

((CloudContactDataStore) contactDataStore).restClient = restClient;

Or in other words you'd need to cast it down to a specific implementation. Dagger 2 doesn't cast down, EVER (at least I've not seen it), because that is usually unsafe.

So, you have two choices. Change the inject(ContactDataStore) method to inject(CloudContactDataStore), or provide a method on ContactDataStore that allows the RestClient to be passed in.

Update: Its not possible to @Inject through abstract, i.e. interface, method.

If you want to inject it through the ContactDataStore API then you have a problem as there is currently a restriction in Dagger 2 (have raised a feature request to remove it) that you cannot mark an abstract method with @Inject. So, in the meantime (or forever if there is some reason why it cannot work in Dagger 2) you will need to do it manually, i.e. get the instance of RestClient from your component method and pass it to the appropriate method on the interface.



来源:https://stackoverflow.com/questions/32947791/why-dagger-inject-is-not-working-but-component-getobject-yes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!