dagger2 cannot find symbol

2019-04-16 22:10发布

问题:

I'm following the Dagger2 sample of TODO app but encounted with 2 errors.

Error1: can't find symbol DaggerNetComponent. (Which is actually there)
Error2: Sharedpreference can't be provided without @provider-annotated method.(Which I think results from error1)

And here's my long but simple code:
Three modules:

@Module
public class AppModule {
    private final Application mApplication;

    AppModule(Application application) {
        mApplication = application;
    }

    @Provides
    Application provideApplication() {
        return mApplication;
    }
}

@Module
public class LoadingModule {
    public final LoadingContract.View mView;

    public LoadingModule(LoadingContract.View mView) {
        this.mView = mView;
    }

    @Provides
    LoadingContract.View provideLoadingContractView() {
        return mView;
    }
}

@Module
public class NetModule {

    @Provides @Singleton
    SharedPreferences providesSharedPreferences(Application application) {
        return PreferenceManager.getDefaultSharedPreferences(application);
    }
}


And two components:

@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface NetComponent {
}

@FragmentScoped
@Component(dependencies = NetComponent.class, modules = LoadingModule.class)
public interface LoadingComponent {
    void inject(LoadingActivity loadingActivity);
}


I get NetComponent in MyApplication:

mNetComponent = DaggerNetComponent.builder()
                .appModule(new AppModule(this))
                .netModule(new NetModule())
                .build();


and LoadingComponent in LoadingActivity:

DaggerLoadingComponent.builder()
                .netComponent(((MyApplication)getApplication()).getNetComponent())
                .loadingModule(new LoadingModule(loadingFragment))
                .build()
                .inject(this);


The only thing that I want LoadingComponent to inject is LoadingPresenter.
Also in LoadingActivity:

@Inject LoadingPresenter mLoadingActivityP; 


And this is how the LoadingPresenter constructed:

public class LoadingPresenter implements LoadingContract.Presenter {
    private SharedPreferences sharedPreferences;
    private LoadingContract.View loadingView;

    @Inject
    public LoadingPresenter(LoadingContract.View loadingView, SharedPreferences sharedPreferences) {
        this.loadingView = loadingView;
        this.sharedPreferences = sharedPreferences;
    }

    @Inject
    void setupListeners() {
        loadingView.setPresenter(this);
    }

    public boolean checkLoginStatus() {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        return sharedPreferences.getBoolean("loginStatus", false);
    }

    @Override
    public void start() {
    }
}


End of my program.
It has been annoying me for several days. Any help is appreciated.

回答1:

You have the causality of your errors backwards. The Dagger* classes are the final output of the annotation processor. Because you had an error in your graph, the Dagger processor couldn't complete, so the output was missing.

The second error is saying that you are requesting SharedPreferences from within a component that doesn't have it bound. Because you've chosen component dependencies rather than subcomponents, all of the bindings from your dependencies are not inherited. In order for your LoadingComponent to use bindings from NetComponent they must be exposed on the component interface. Adding SharedPreferences sharedPreferences(); to NetComponent or switching to subcomponents should fix your problem.

See the @Component docs and the page on subcomponents in the user's guide for more information.