0

I am using MVP Architecture along with Dagger2. I want to get Context in my Presenter using constructor injection.

My Activity :

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_appintroduction);
        activityComponent().inject(this);
        ButterKnife.bind(this);
        skipall.bringToFront();
     }

My Presenter:

@ConfigPersistent

    public class AppIntroPresenter extends BasePresenter<AppIntroMvpView> {

        private final DataManager mDataManager;
        private final Context ctx1;


        @Inject
        public AppIntroPresenter(DataManager dataManager,Context context) {
            mDataManager = dataManager;
            ctx1=context;

        }

        public void openCamView(Context ctx) {

            ctx.startActivity(new Intent(ctx, CameraActivity.class));
        }
    }

My Application Component :

@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {

    void inject(SyncService syncService);

    @ApplicationContext Context context();
    Application application();
    RibotsService ribotsService();
    PreferencesHelper preferencesHelper();
    DatabaseHelper databaseHelper();
    DataManager dataManager();
    RxEventBus eventBus();
    ClassService classService();
    AnsweredQuestionService answeredQuestionService();
}

My Activity Component:

@PerActivity
@Subcomponent(modules = ActivityModule.class)
public interface ActivityComponent {

    void inject(MainActivity mainActivity);
    void inject(CameraActivity cameraActivity);
    void inject(AppIntroActivity appIntroActivity);

}

My Application Module:

@Module
public class ApplicationModule {
    protected final Application mApplication;

    public ApplicationModule(Application application) {
        mApplication = application;
    }

    @Provides
    Application provideApplication() {
        return mApplication;
    }

    @Provides
    @ApplicationContext
    Context provideContext() {
        return mApplication;
    }

    @Provides
    @Singleton
    RibotsService provideRibotsService() {
        return RibotsService.Creator.newRibotsService();
    }

    @Provides
    @Singleton
    ClassService provideClassService() {
        return ClassService.Creator.newClassService();
    }

    @Provides
    @Singleton
    AnsweredQuestionService provideAnsweredQuestionService() {
        return AnsweredQuestionService.Creator.newAnsweredQuestionService();
    }



}

My Activity Module:

@Module
public class ActivityModule {

    private Activity mActivity;

    public ActivityModule(Activity activity) {
        mActivity = activity;
    }

    @Provides
    Activity provideActivity() {
        return mActivity;
    }

}

After running the code, i get error:

Error:(17, 8) error: [uk.co.ribot.androidboilerplate.injection.component.ActivityComponent.inject(uk.co.ribot.androidboilerplate.ui.AppIntro.AppIntroActivity)] android.content.Context cannot be provided without an @Provides-annotated method.
android.content.Context is injected at
uk.co.ribot.androidboilerplate.ui.AppIntro.AppIntroPresenter.<init>(…, context)
uk.co.ribot.androidboilerplate.ui.AppIntro.AppIntroPresenter is injected at
uk.co.ribot.androidboilerplate.ui.AppIntro.AppIntroActivity.mAppIntroPresenter
uk.co.ribot.androidboilerplate.ui.AppIntro.AppIntroActivity is injected at
uk.co.ribot.androidboilerplate.injection.component.ActivityComponent.inject(appIntroActivity)

I know when i add context to constructor injection in My Presenter i get this error, but i am not able to figure out why? If i remove the context from constructor :

@Inject
        public AppIntroPresenter(DataManager dataManager,Context context) {
            mDataManager = dataManager;
            ctx1=context;

        }

Then everything works fine. But i need the context from injection. Please help me with this?

Uday Khatry
  • 449
  • 1
  • 8
  • 23
  • Actually why to put context in the presenter? The presenter should tell view to do actions related to context(e.g. showing a Toast, etc) – matrix Dec 04 '17 at 14:24
  • Thanx matrix, but we want get uri of our saved image : Uri photoURI = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", file); Hence, we need we need application context in the presenter. – Uday Khatry Dec 05 '17 at 07:33
  • no you do not because from what you say you want to get Uri to use it in Intent. So when you need to do something with Intent you will tell the view addDataToIntent(String filepath) and in the view you will create this with Context. The presenter must have no import from android.*;. Keep this in mind for the future. You can take your models and presenters and just change the view and build a web application. – matrix Dec 05 '17 at 10:36
  • can i pass context as param from activity to presenter? – Uday Khatry Dec 05 '17 at 11:33
  • Dagger doesn't know any `Context`, it only knows `@ApplicationContext Context` (see in your module/component). If you want to use `Context` then you either need to add an unnamed / unqualified one to your component or subcomponent, or add the qualified annotation to your constructor argument and request the application context. – David Medenjak Dec 05 '17 at 11:43
  • Again, you shouldn't do context related actions in the Presenter. The presenter should tell Activity to do them. – matrix Dec 05 '17 at 15:24

1 Answers1

0

Since your constructor has members, you need to create a module and create there an instance annotated with @Provides and @Singleton, same as ApplicationModule.

Cătălin Florescu
  • 5,012
  • 1
  • 25
  • 36
  • But why can't i get Context in my Presenter constructor. I am able to get Data Manager in my constructor and according to : My Application Component, I have @ApplicationContext Context context();. So i should be able to get context as well in my constructor? – Uday Khatry Dec 04 '17 at 14:18
  • I think you should add also App module, so: `@Subcomponent(modules = {ActivityModule.class, ApplicationModule.class})` – Cătălin Florescu Dec 05 '17 at 07:56
  • Hi Florescu, can you add a sample code of the component and the presenter where i will be receiving the context? – Uday Khatry Dec 05 '17 at 11:35