I've created a component and it only last for the lifetime of the activity. I did not use any scope annotations and only quick example of the life time of the component looks like this:
public class MainActivity extends AppCompatActivity {
private final String TAG = getClass().getSimpleName();
@Inject
AlmondButter someAlmondButter;
@Inject
CashewSandwich sandwich;
SandwichComponent sandwichComponent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*create thte dependent butter for the sandwich here*/
ButterComponent butterComponent=DaggerButterComponent.builder().
butterModule(new ButterModule()).build();
/*create a scope sandwichcomponent here */
sandwichComponent=DaggerSandwichComponent.builder().sandwichModule(new SandwichModule()).
butterComponent(butterComponent)
.build();
//finally we have a sandwichComponent, lets inject our dependencies
sandwichComponent.inject(this);
Log.v(TAG,sandwich.toString());
Log.v(TAG,someAlmondButter.toString());
}
@Override
protected void onDestroy() {
super.onDestroy();
//not necessary but it clearly shows the scope being tied to lifecycle of activity
sandwichComponent=null;
}
}
none of my components are scoped with anotations and it works fine. So im confused why some recommend to create scope tags, what is there purpose ? i'll show you my components below for reference:
@Component(dependencies = ButterComponent.class, modules = SandwichModule.class)
public interface SandwichComponent {
CashewSandwich ProvideCashewSandwitch();
void inject (MainActivity mainactivity);
}
and the next component:
@Component(modules={ButterModule.class})
public interface ButterComponent {
//these are for our whatever class depends on butter
AlmondButter ProvideAlmondButter();
CashewButter ProvideCashewButter();
}
UPDATE: FOR ANYONE WHO NEEDS HELP WITH UNDERSTANDING THESE CONCEPTS I MADE A BLOG HERE.
By using scopes on component and scopes on module provider method, you can ask Dagger2 to create
scoped providers
for you.In order to get a scoped provider in your module's provider method, you must put the scope on the component as well.
You can specify only one scope on a given component, and in a scoped component, you can only have modules with that scope on its provider methods, or the provider methods can also be unscoped.
Unscoped providers give you a new instance on every inject call. Scoped providers store a single instance for every inject call to that specific component instance.
It is also worth noting that if you subscope another component to inherit its dependencies (using subcomponent or component dependency), you can only depend on one other scoped component. Think of it like how "multiple inheritance" is not allowed in Java, you also cannot depend on multiple scoped components and inherit their dependencies, only one.
Typically you have a singleton scope, and you subscope your components according to the top-level separation of modules in your application.
According to Martin Fowler, the right way to slice your application into pieces on the top-level is by features, such as
GalleryComponent
,SettingsComponent
, etc. and not by layers (data, domain, presentation).Scopes manage the instance creation across multiple requests for the same type. Imagine if you had this:
This would create two separate
AlmondButter
instances. A trivial case, but hopefully it illustrates the point that each time you request the dependency, a new one is created.Imagine now you have two different classes, each with a field
@Inject AlmondButter sharedAlmondButter
. If you want them to have the same exact instance, a scope will handle that for you.Similarly, with any dependency you have, you can inject a
Provider<T>
, i.e.@Inject Provider<AlmondButter> almondButterProvider
. This can allow you to callalmondButterProvider.get()
to retrieve a new instance. If you then wanted all values returned by.get()
to be the same instance, a scope would accomplish the same thing.