I have an Activity and its presenter, both being injected with an Adapter. The Activity needs the adapter to set on the RecyclerView and the presenter needs it to call update methods (eg: notifyItemChanged
) when data is changed.
The problem is that because the adapter is injected twice, the presenter and the activity don't have the same instance of it. I need Dagger to create only one instance of it. However, the Adapter needs the Activity's context and has @ActivityScope
to prevent memory leaks, which means I cannot also use @Singleton
scope on it.
Is there something I don't understand? Is there a way to inject the adapter in both classes, without setting it manually with a setAdapter
method in the presenter or the Activity? Or is there a way to limit the number of instances of Adapter created?
EDIT: Dependency injection files:
@Module
public interface MainModule {
@ActivityContext @Binds
Context context(MainActivity activity);
@ActivityScope @Binds
MainContract.Presenter presenter(MainPresenter presenter);
// CHILD FRAGMENT
@FragmentScope @ContributesAndroidInjector
ChildFragment childFragment();
@ActivityScope @Binds
ChildContract.Presenter childPresenter(ChildPresenter presenter);
@ActivityScope @Binds
ChildContract.AdapterView adapterView(MyAdapter adapter);
}
ChildFragment
, ChildPresenter
and MyAdapter
classes are annotated with @ActivityScope
.
This is the only way I got it to work and seems wrong to me because ChildPresenter and MyAdapter are only used from the fragment. However, annotating them with @FragmentScope
threw up error: "may not reference bindings with different scopes". Also, the fragment "provider" and and fragment itself are annotated with two different scopes?
In an MVP architecture, the presenter should only care about business logic. That means the the presenter does not know anything about Android stuff and does not contain any Android specific items.
In your case you wrote that your presenter holds an adapter and calls the notifyItemChanged
methode on it. This is an Android specific item and should not work that way. The view is the one responsible for holding the adapter and any interaction from the presenter to the adapter should happen via the view.
What that means for your example:
notifyAdapterItemChanged
notifyAdapterItemChanged
(and the view in turn calls the adapter)side note: If you need the provide data the other way around (from the adapter to the presenter) I would suggest adding a special adapterInterface to the presenter that you can keep as a weakReference in the adapter.
Hope that helps and let me know if you have any additional questions...