Difference in the use of scopes in Dagger 2 - android

I use Dagger 2 to perform Dependency Inversion rule in my app. I was just looking on Clean Architecture example by Fernando Cejas and I had a question - what is difference between the two approaches presented below:
If I mark the class like so:
#Singleton // or #PerActivity or #PerFragment, nevermind
public class UserDataStoreFactory {
private final Context context;
private final UserCache
}
Or if I create a module, where I define a provide-method and add this module into the any component (PerActivity, PerFragment and so on, nevermind)
#Module
public class SomeModule {
#Provides
#Singleton // or #PerActivity or #PerFragment, nevermind
UserDataStoreFactory providesUserDataStoreFactory (Context context, UserCache userCache) {
return new UserDataStoreFactory(context, userCache)
}
}

The two approaches are the same: Both will allow your UserDataStoreFactory to be injected throughout your application in the Singleton (or #PerActivity/#PerFragment/nevermind) scope.
The former approach, marking the class with the scope, will only work if the class has an #Inject-annotated constructor. The second approach does not require that constructor annotation, but does also require additional boilerplate code that is subject to change when the constructor arguments change. This makes the first approach more resilient to dependency changes on UserDataStoreFactory, even though they both achieve the same end result in your graph; however, the first approach may only be possible if the class is code you can change, or that is otherwise structured for scoped dependency injection.

Related

How inject dagger non empty constructor module dependencies to hilt

Hilt is not supportting non epmty constructor modules. If we need to migrate partially to Hilt from dagger , how we can inject dependencies from legacy dagger modules having non empty constrctors to hilt components such as HiltViewModel.
// Legacy Dagger module
#Module
public class DaggerModule {
private final Boolean customBoolean;
DaggerModule(Boolean customBoolean) {
this.customBoolean = customBoolean;
}
#Provides
#Singleton
CustomClass provideCustomClass() {
return CustomClass(customBoolean);
}
}
#Module
public class AnotherDaggerModule {
#Provides
#Singleton
AnotherClassDepndsOnCustomClass provideAnotherClass(CustomClass customClass) {
return AnotherClassDepndsOnCustomClass(customClass);
}
}
// Migrated Hilt module
#HiltViewModel
class HiltViewModel #Inject constructor(
  private val anotherClass: AnotherClassDepndsOnCustomClass
) : ViewModel() {
  ...
}
Since we are not using components to pass some custom parameters while initialising modules, is there any solution which I'm not aware already exists?
While running the app, the app crashing with error DaggerModule must be set.
You'll need to refactor.
The documentation on Migrating to Hilt describes this case under the heading "Handling Component Arguments", since instantiable modules would otherwise be treated as component arguments passed through a Builder or Factory:
Hilt components cannot take component arguments because the initialization of the component is hidden from users. [...]
If your component has any other arguments either through module instances passed to the builder or #BindsInstance, read this section on handling those. Once you handle those, you can just remove your #Component.Builder interface as it will be unused.
Under "Component arguments" the Hilt documentation confirms that a refactor is required:
Because component instantiation is hidden when using Hilt, it is not possible to add in your own component arguments with either module instances or #BindsInstance calls. If you have these in your component, you’ll need to refactor your code away from using these.
You can consider some of these structures:
Replacement module / subclassing Modules
In your example, you might need to create a replacement Module that provides a binding for CustomClass. This might be as straightforward as subclassing the Module and providing a public no-arg constructor that provides the super(value) constructor call your module needs. If your Module would only ever get a single value in your graph (but might get a different value in a separate application), then this might be enough.
#Module
public class AdaptedDaggerModule extends DaggerModule {
AdaptedDaggerModule() {
super(true);
}
}
Note that module subclasses are somewhat limited in utility, and should not be used for testing overrides.
Custom subcomponents
However, you also wrote "components are created in respective modules where we need to use" in a comment, and you can continue doing so using custom subcomponents in Hilt, with more comprehensive documentation in javadoc or the main Dagger subcomponent documentation. Because you would create this component through an explicit call to a Builder or Factory, you could provide the Module instance there. Subcomponents inherit bindings from their parent components, so you could avoid specifying your entire list of Modules.
Note that doing this as a subcomponent is mostly valuable when you have a dense tree with multiple references to the instance you're providing in the constructor. If this is simply a matter of combining graph-based constructor arguments with one-off constructor arguments, assisted injection is probably a better option.
/** Subcomponents are usually declared on modules. You can also reuse one you have. */
#Module(subcomponents={YourSubcomponent.class})
public interface IncludeThisInYourHiltModuleList {}
#Subcomponent(modules={DaggerModule.class, AnotherDaggerModule.class})
public interface YourSubcomponent {
AnotherClassDepndsOnCustomClass anotherClass();
#Subcomponent.Builder
interface Builder {
Builder daggerModule(DaggerModule daggerModule); // arbitrary name
YourSubcomponent build(); // arbitrary name
}
}
#HiltViewModel
class HiltViewModel #Inject constructor(
private val yourSubcomponentBuilder: YourSubcomponent.Builder
) : ViewModel() {
fun yourMethod() {
val subcomponent =
yourSubcomponentBuilder.daggerModule(DaggerModule(false)).build()
val anotherClass = subcomponent.anotherClass()
// ...
}
}
Constructor values in Hilt-managed components
The most difficult case would be where your Module would want separate values in each of your Hilt-managed components, e.g. each Activity needing to pass a different constructor argument. In that case you might need to rephrase the customBoolean (or other parameters) as deriving the value from the Activity instance itself. This maintains Hilt's expectation that it can create an Activity component for each Activity instance that Android unpredictably creates or recreates, and it can do so without specifying any other constructor parameters.

Dagger 2: Inject child class based on logic

Using Dagger 2 in my android with MVP pattern, and struggling a little with some concepts.
Let's say I have a presenter DashboardPresenter, I am injecting it when I need it in an activity or other presenters, by using:
#inject
DashboardPresenter presenter;
or in the constructor of other presenters:
#inject
public AccountPresenter(DashboardPresenter presenter) {
//init
}
Now I'm not very sure how it works, but I want to do the following:
Let's say I create a BaseDashboardPresenter which will be the parent
And I create 2 children for it: NormalDashboardPresenter and ProDashboardPresenter both extends from it.
When I want to use it in an activity or another presenter, I inject the Base presenter by calling
#inject
BaseDashboardPresenter presenter;
And I override the #inject behavior, to inject one of the children based on a boolean.
So something like this:
//in BaseDashboardPresenter
override inject() {
if(Utility.checkIfUserIsPro()) {
inject ProDashboardPresenter();
} else {
inject NormalDashboardPresenter();
}
}
so from my activity I just call the abstract methods in the Base class, and the difference is only which child is injected.
Is this possible?
Happy to provide more clarification if needed.
Contrary to the other answer I believe that your modules should not include any logic. That's just not what one would expect.
Also, how would your #Provides method look if one variant needs A, while the other depends on B? Now you need to declare dependencies that you don't need and it just gets more confusing from here on.
Instead you should create one module for every option and include the correct module in your component.
// module providing pro version
componentBuilder.addPresenterModule(new ProModule());
// or a default one
componentBuilder.addPresenterModule(new DefaultModule());
That way wherever you build your component you get to decide what's supposed to be in it. An even more dedicated approach would be to use 2 completely different components where each component uses different modules etc. This might make sense for more complex projects, but in your case it seems that modules would be enough.
To do this, you should add in your module something like this:
#Provides
public BaseDashboardPresenter provideDashboardPresenter(OtherPresenter presenter) {
if (Utility.checkIfUserIsPro()) {
return new ProDashboardPresenter();
} else {
return new NormalDashboardPresenter(presenter);
}
}

How do I use AndroidInjection class in custom views or other android classes?

My issue with the Android-specific pattern is, if you use their AndroidInjection class, there is no way to members inject other objects besides Activities/Fragments/custom views/adapters, except with the Application Component. This is because you cannot get a reference the the Subcomponent (AndroidInjector) used to inject Activities/Fragments.
This makes injecting Dialogs (if you use DialogFragments).
The AndroidInjection class seems to support just the core Android types.
What follows is not an answer to your question, but an explanation why you shouldn't be asking this question at all.
You should avoid injections into custom Views in general. The reasons for this are listed in this article.
Advantages of using Method Injection in this case [injection into custom Views] are:
Dependencies will need to be propagated from top level component (Activity or Fragment)
Method Injection does not open door to Single Responsibility Principle violation
No dependency on the framework
Better performance
The first advantage might come as a surprise because propagation from
top level component is harder than adding annotation to fields, and
involves more boilerplate code. This is surely a bad thing, right?.
Not in this case. In fact, there are two good aspects associated with
such a propagation of dependencies. First of all, the dependencies
will be visible at the top level component. Therefore, just by looking
at e.g. Fragment‘s fields, the reader of the code will immediately
understand that this Fragment shows images. Such optimizations for
readability makes the system more easily maintainable in the long
term. Secondly, there are not many use cases in which sub-classes of
View need additional dependencies. The fact that you need to actually
work in order to provide these dependencies will give you a bit of
time to think about whether providing them is a good design decision
to start with.
The second advantage is related to collaborative construction. You
might be very experienced software engineer yourself, but you’ll
probably have also less experienced teammates. Or it is possible that
you’ll leave the project one day, and the guy who will take over will
not be as good as you. By injecting one single dependency using a
framework, you basically open a door for other injections. Imagine
that some data from SharedPreferences becomes required in custom View
in order to e.g. fix a bug. One of the less experienced developers
might decide that it is a good approach to inject SharedPreferences
into custom View directly. Doing this violates Single Responsibility
Principle, but that developer might not even be aware of such a
concept. Therefore, in the long term, such injection “backdoors” can
reduce design quality and lead to long debug sessions.
The third advantage of using Method Injection with custom Views is
that you don’t couple the View to dependency injection framework. Just
imagine that few years from now you (or some other poor guy) need to
replace the framework. The fact that you’ll probably have tens of
Activities and Fragments to start with will make your life miserable.
If you’ll have additional tens or hundreds of custom Views to handle,
then it might bring you into suicidal mood.
The last (but not least) advantage is performance. One screen can
contain one Activity, several Fragments and tens of custom Views.
Bootstrapping this number of classes using dependency injection
framework might degrade application’s performance. It is especially
true for reflection based frameworks, but even Dagger carries some
performance cost.
In addition, I advice to avoid the new injection method that involves AndroidInjection class. It is discussed in this video tutorial.
First, you should think over Vasily's answer.
But let's think for a moment how we did this before Dagger Android?
We built a subcomponent from the component that was taken from the Application class. Later, we could use this subcomponent in order to inject fields, for example, of a custom view.
So, we'll try to do the exact same thing now.
Suppose, our aim is to inject MyAdapter class into a MyButton:
public class MyButton extends AppCompatButton {
#Inject MyAdapter adapter;
public MyButton(Context context) {
super(context);
...
}
}
And let's make the adapter have a dependency on the activity Context, not application Context:
public class MyAdapter {
#Inject
public MyAdapter(#Named("activity") Context context) {
}
}
Let's start with the custom Application class.
MyApplication.java
public class MyApplication extends DaggerApplication {
#Inject
DispatchingAndroidInjector<Activity> dispatchingActivityInjector;
public static MySubcomponent mySubcomponent;
#Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder()
.create(this);
}
}
AppComponent.java:
#Component(modules = {AndroidSupportInjectionModule.class, ActivityBindingModule.class, AppModule.class})
#Singleton
public interface AppComponent extends AndroidInjector<MyApplication> {
#Component.Builder
abstract class Builder extends AndroidInjector.Builder<MyApplication> {
}
}
AppModule.java
#Module
abstract class AppModule {
#Binds
#Singleton
#Named("app")
abstract Context providesContext(Application application);
}
ActivityBindingModule.java
#Module(subcomponents = MySubcomponent.class)
public abstract class ActivityBindingModule {
#Binds
#IntoMap
#ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity>
bindMainActivityInjectorFactory(MySubcomponent.Builder builder);
}
AndroidSupportInjectionModule.java is shipping with dagger itself. If you do not use classes from support package (i.e. android.support.v4.app.Fragment instead of android.app.Fragment), then use AndroidInjectionModule.java.
MySubcomponent.java
#ActivityScope
#Subcomponent(modules = {SubcomponentModule.class/*, other modules here, if needed */})
public interface MySubcomponent extends AndroidInjector<MainActivity> {
void inject(MyButton button);
#Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity> {
public abstract MySubcomponent build();
}
}
SubcomponentModule.java
#Module
abstract class SubcomponentModule {
#Binds
#ActivityScope
#Named("activity")
abstract Context toContext(MainActivity activity);
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Inject
MySubcomponent subcomponent;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Will inject `subcomponent` field
AndroidInjection.inject(this);
// Saving this component in a static field
// Hereafter you are taking responsibility of mySubcomponent lifetime
MyApplication.mySubcomponent = subcomponent;
super.onCreate(savedInstanceState);
setContentView(new MyButton(this));
}
}
Having all of these, now here's how MyButton will look like:
public class MyButton extends AppCompatButton {
#Inject MyAdapter adapter;
public MyButton(Context context) {
super(context);
MyApplication.mySubcomponent.inject(this);
}
}
I admit that this looks hacky and certainly not an approach to stick to. I'm happy to see a better approach.
This is because you cannot get a reference the the Subcomponent (AndroidInjector) used to inject Activities/Fragments.
You can always just inject the component itself. Just add a field for the component to your Activity / Fragment and let Dagger inject it along with the rest.
// will be injected
#Inject MainActivitySubcomponent component;
The issue of whether the dagger-android classes like AndroidInjector should support injection inside Views or not has been discussed in the following Github issue:
https://github.com/google/dagger/issues/720
Quoting from one of the library authors:
There is both a philosophical point and logistical/implementation point to be made here.
First, it's not fully clear to us that injecting views is the right thing to do. View objects are meant to draw, and not much else. The controller (in a traditional MVC pattern) is the one which can coordinate and pass around the appropriate data to a view. Injecting a view blurs the lines between fragments and views (perhaps a child fragment is really the appropriate construct instead?)
From the implementation perspective, there is also a problem in that there isn't a canonical way to retrieve the View's parent Fragments (if any), or Activity to retrieve a parent component. There have been hacks suggested to build in that relationship, but so far we haven't seen anything that seems to suggest that we could do this correctly. We could just call View.getContext().getApplicationContext() and inject from there, but skipping the intermediate layers without any option for something in between is inconsistent with the rest of our design, and probably confusing to users even if it works.
This reinforces the opinion expressed in Vasily's answer.
To add further, people often seem to want to inject model-layer dependencies inside their custom views. This is a bad idea as it goes against the software engineering principle of separation of concerns.
The correct solution for associating a view and a model is to write an adapter like the adapters for RecyclerView and ListView. You can inject the model-layer dependency at the Fragment or Presenter level and set the adapter there.

Android | Dagger 2. Injecting different subclasses into Fragment depending of a condition

I am working with MVP and Dagger 2 DI. I have a Fragment that I reuse in a few activities. I have an interface type for presenter as a property of the Fragment, say MVPPresenter. Depending in which activity the Fragment is being used, I need to inject different presenters into it (each presenter is an implementation of MVPPresenter). So I need a way to inject each implementation of MVPPresenter into the Fragment as I need.
Currently, I have a terrible solution, which works, but it is simply wrong and creates unnecessary objects that are never used. Here is the code:
public class MyFragment {
...
#Inject
public void setPresenter(#NonNull ProfilePresenter presenter) {
if (mAdapter instanceof ProfileAdapter) {
this.presenter = presenter;
}
}
#Inject
public void setPresenter(#NonNull ContactsPresenter presenter) {
if (mAdapter instanceof ContactsAdapter) {
this.presenter = presenter;
}
}
...
}
Here is my Module:
#Module
class PresentersModule {
#Provides
#Singleton
ProfilePresenter ProfilePresenter() {
return new ProfilePresenter();
}
#Provides
#Singleton
ContactsPresenter ContactsPresenter() {
return new ContactsPresenter();
}
}
You see, depending on Adapter type, I assign presenter, or do not. I know this is stupid and all. Problem is that Dagger needs exact type to inject to be specified and Interface type wont work.
What is the proper way of dealing with such cases?
You have, as I see it, three solutions of varying degrees of weight.
Inject two choices as you have now: If you know all of your Fragment's use-cases up front, and you don't need to vary the dependency graphs any more than on a single class, you can do so easily using a similar method to what you have now. My variant uses Providers, which are bound automatically for any object in your graph, so that you don't unnecessarily create whole trees of objects; also, #Inject methods can take an arbitrary parameter list, so you can do all of your method injection in one method if you choose.
#Inject
public void setPresenter(
#NonNull Provider<ContactsPresenter> contactsPresenterProvider,
#NonNull Provider<ProfilePresenter> profilePresenterProvider) {
if (mAdapter instanceof ContactsAdapter) {
this.presenter = contactsPresenterProvider.get();
} else if (mAdapter instanceof ProfileAdapter) {
this.presenter = profilePresenterProvider.get();
}
}
The other two solutions involve multiple components: Instead of saying "there is one way of binding my graph together", you're effectively asking Dagger to generate multiple options for you, which means that your graphs can vary widely but stay consistent. This technique might be more useful if you reuse objects in different ways for different sections of your application, like if you have a Profile section and a Contacts section, each of which using a common A injecting a common B injecting a common C injecting a different D. To consistently support two deep graphs like that, child components are a much better option.
Use component dependencies: As in rst's answer, you can use component dependencies to isolate your fragments. They did a pretty good job of explaining, so I'll not repeat that here. You should be aware, though, that component dependencies can only consume bindings that are exposed on the component you depend on: Even if Foo and Bar are bound on DiComponent, you won't be able to access them from your ProfileComponent or ContactsComponent unless you put Foo getFoo() and Bar getBar() on your DiComponent. (That said, component dependencies don't have to be Dagger components, either; they can be arbitrary types that you implement yourself or let Dagger implement for you.)
Use subcomponents: Though rst alluded to subcomponents, I think they warrant a bit more explaining, particularly because they are a core component of the recently-released dagger.android functionality, and because Fragments and other UI pieces can be difficult to extract with component dependencies—subcomponents implicitly and automatically inherit bindings from the surrounding component, so you don't have to explicitly expose bindings on your DiComponent. See other differences at this SO question.
#Component
public interface DiComponent {
ProfileComponent getProfileComponent(); // Dagger generates implementations
ContactsComponent getContactsComponent(); // as part of DiComponent.
}
#Subcomponent(modules={ContactsModule.class})
public interface ContactsComponent {
void inject(MyFragment myFragment);
}
#Module
public interface ContactsModule {
#Binds MvpPresenter bindMvpPresenter(ContactsPresenter contactsPresenter);
}
#Subcomponent(modules={ProfileModule.class})
public interface ProfileComponent {
void inject(MyFragment myFragment);
}
#Module
public interface ProfileModule {
#Binds MvpPresenter bindMvpPresenter(ProfilePresenter profilePresenter);
}
In the above, the root DiComponent doesn't have a binding for MvpPresenter, so in itself it can't inject MyFragment. However, ProfileComponent and ContactsComponent can, and each will use different graphs configured in the corresponding Modules (but silently inheriting common bindings from DiComponent's modules). If the graphs vary differently further down, like with each MvpPresenter using the same Validator but with a different ProfileValidationRule versus ContactsValidationRule, you could bind ValidationRule to those different classes in your different Modules to get different behavior.
(For completeness, you would usually also have the option to use a factory like AutoFactory and pass in a parameter like the presenter to your specific container like Fragment. However, this is only really an option if you're creating your instances, and not really an option when Android forces a zero-arg public constructor so it can create Fragment instances at will.)
Looking through the names you've given to mvp-presenters, one could conclude, their complementary mvp-views should rather be separated and implemented in different fragments.
But if you wish to maintain things as-is, having only single setPresenter method declared in your fragment, probably the easiest way to deal with your problem would be to introduce separate components with complementary modules for providing desirable presenter implementations.
For this solution to work you would need to adjust your fragment to contain single declaration of setPresenter method with MVPPresenter type as an argument:
#Inject
public void setPresenter(#NonNull MVPPresenter presenter) {
this.presenter = presenter;
}
Afterwards, you'd need to provide components exposing inject(...) method and declaring usage of appropriate module. As those dependency graphs would be dependent on main component instance, they should get their own scope (tied to activity or fragment, depending on what class is actually holding the graph object).
For instance, if you were using DiComponent for providing all your dependencies with scope defined via #Singleton annotation, you'd need to declare #MyFragmentScope annotation and provide components, dependent on above-mentioned DiComponent, in order to declare injectable presenters:
import javax.inject.Scope;
#Scope
public #interface MyFragmentScope {
}
Your dependent components would look like:
#MyFragmentScope
#Component(dependencies = DiComponent.class, modules = ProfileModule.class)
public interface ProfileComponent {
void inject(MyFragment fragment);
}
with complementary module:
#Module
public class ProfileModule {
#Provides
#MyFragmentScope
MVPPresenter providesProfilePresenter() {
return new ProfilePresenter();
}
}
Note: return type is MVPPresenter, not concrete implementation.
Similarly you'd need to create ContactsComponent and ContactsModule for your ContactsPresenter.
Eventually you should use proper component instance to perform the injection. Now instead of using
diComponent.inject(myFragment)
you should use component which would provide desirable dependency.
At this point you would actually have a switch defining which presenter should be used.
In case of ProfilePresenter injecting you'd need to use:
DaggerProfileComponent.builder()
.diComponent(diComponent)
.build()
.inject(myFragment);
Or in case of ContactsPresenter injecting you'd need to use:
DaggerContactsComponent.builder()
.diComponent(diComponent)
.build()
.inject(myFragment);
It's rather common practice to use separate components for smaller parts of application like activities. It's possible to either declare such components as regular dependent ones or as sub components (see #Subcomponent documentation for reference). Starting from Dagger 2.7 there is a new way of declaring Subcomponents via #Module.subcomponents. Due to this fact there's an opportunity to decouple AppComponent from Activities Subcomponents. You may refer to sample GitHub repository from frogermcs for reference. He also has a great complementary blog post on this topic.

Dagger 2 Custom Scope for each Fragment (or Activity etc...)

I've looked at a couple different articles which seem to suggest two different ways of doing custom scoping in Dagger 2:
MVP Presenters that Survive Configuration Changes Part-2 (Github repo):
Uses unique custom scopes for each fragment, e.g. #Hello1Scope and #Hello2Scope for Hello1Fragment and Hello2Fragment respectively
Tasting Dagger 2 on Android:
Uses a single custom scope for all fragments, e.g. #PerFragment.
From what I understand, it seems that, as in method 2, it should be okay to have a single scope defined that can be used for all fragments (i.e., #PerFragment). In fact (please correct me if I'm wrong), it seems like the name of the custom scope is irrelevant, and it's only where the subcomponent is created (i.e. in Application, Activity, or Fragment) that matters.
Is there any use case for defining a unique scope for each fragment such as in case 1?
After reading the answer by #vaughandroid, and What determines the lifecycle of a component (object graph) in Dagger 2? I think I understand custom scopes well enough to answer my own question.
First, here are a couple rules when dealing with components, modules, and scoping annotations in dagger2.
A Component must have a (single) scope annotation (e.g. #Singleton or #CustomScope).
A Module does not have a scope annotation.
A Module Method may have a (single) scope that matches its Component or no scope, where:
Scoped: means a single instance is created for each instance of the component.
Unscoped: mean a new instance is created with each inject() or provider call
NOTE: Dagger2 reserves #Singleton for the root Component (and it's modules) only. Subcomponents must use a custom scope, but the functionality of that scope is exactly the same as #Singleton.
Now, to answer the question: I would say create a new named scope for each conceptually different scope. For example, create a #PerActivity, #PerFragment, or #PerView annotation that indicates where the component should be instantiated, and thus indicating its lifetime.
Note: this is a compromise between two extremes. Consider the case of a root component and n subcomponents you will need:
at least 2 annotations (#Singleton and #SubSingleton), and
at most n+1 annotations (#Singleton, #SubSingleton1, ... #SubSingletonN).
Example:
Application:
/** AppComponent.java **/
#Singleton
#Component( modules = AppModule.class )
public interface AppComponent{
void inject(MainActivity mainActivity);
}
/** AppModule.java **/
#Module
public class AppModule{
private App app;
public AppModule(App app){
this.app = app;
}
// For singleton objects, annotate with same scope as component, i.e. #Singleton
#Provides #Singleton public App provideApp() { return app; }
#Provides #Singleton public EventBus provideBus() { return EventBus.getDefault(); }
}
Fragment:
/** Fragment1Component.java **/
#PerFragment
#Component( modules = {Fragment1Module.class}, dependencies = {AppComponent.class} )
public interface Fragment1Component {
void inject(Fragment1 fragment1);
}
/** Fragment1Module.java **/
#Module
public class Fragment1Module {
// For singleton objects, annotate with same scope as component, i.e. #PerFragment
#Provides #PerFragment public Fragment1Presenter providePresenter(){
return new Fragment1Presenter();
}
}
/** PerFragment.java **/
#Scope
#Retention(RetentionPolicy.RUNTIME)
public #interface PerFragment {}
Your understanding is correct. The named scopes allow you to communicate intention, but they all work the same way.
For scoped provider methods, each Component instance will create 1 instance of the provided object.
For unscoped provider methods, each Component instance will create a new instance of the provided object whenever it needs to inject it.
The lifetime of the Component instance is important though. 2 different instances of the same component will provide different object instances, even scoped ones.
Scope names should indicate the lifetime of the provided object (which matches that of the Component instance) so #PerFragment makes much more sense to me.
From a quick look at the "MVP Presenters..." tutorial, it's not clear to me exactly what the author's intention is with having separate scopes. Since the names are just throwaway ones, I wouldn't read too much into it.

Categories

Resources