1# Dagger 2 in SystemUI
2*Dagger 2 is a dependency injection framework that compiles annotations to code
3to create dependencies without reflection*
4
5## Recommended reading
6
7Go read about Dagger 2.
8
9 - [User's guide](https://google.github.io/dagger/users-guide)
10
11## State of the world
12
13Dagger 2 has been turned on for SystemUI and much of
14[Dependency.java](../src/com/android/systemui/Dependency.java)
15has been converted to use Dagger. Since a lot of SystemUI depends on Dependency,
16stubs have been added to Dependency to proxy any gets through to the instances
17provided by dagger, this will allow migration of SystemUI through a number of CLs.
18
19### How it works in SystemUI
20
21There are three high level "scopes" of concern in SystemUI. They all represent
22singleton scopes, but serve different purposes.
23
24* `@Singleton` - Instances that are shared everywhere. There isn't a  lot of
25   code in this scope. Things like the main thread, and Android Framework
26   provided instances mostly.
27* `@WMShell` - WindowManager related code in the SystemUI process. We don't
28   want this code relying on the rest of SystemUI, and we don't want the rest
29   of SystemUI peeking into its internals, so it runs in its own Subcomponent.
30* `@SysUISingleton` - Most of what would be considered "SystemUI". Most feature
31   work by SystemUI developers goes into this scope. Useful interfaces from
32   WindowManager are made available inside this Subcomponent.
33
34The root dagger graph is created by an instance of `SystemUIInitializer`.
35See [README.md](../README.md) for more details.
36For the classes that we're using in Dependency and are switching to dagger, the
37equivalent dagger version is using `@Singleton` and therefore only has one instance.
38To have the single instance span all of SystemUI and be easily accessible for
39other components, there is a single root `@Component` that exists that generates
40these. The component lives in
41[ReferenceGlobalRootComponent.java](../src/com/android/systemui/dagger/ReferenceGlobalRootComponent.java).
42
43### Adding a new injectable object
44
45First annotate the constructor with `@Inject`. Also annotate it with
46`@SysUISingleton` if only one instance should be created.
47
48```kotlin
49@SysUISingleton
50class FeatureStartable
51@Inject
52constructor(
53/* ... */
54) {
55    // ...
56}
57```
58
59If you have an interface class and an implementation class, Dagger needs to
60know how to map it. The simplest way to do this is to add an `@Binds` method
61in a module. The type of the return value tells dagger which dependency it's
62providing:
63
64```kotlin
65@Module
66abstract class FeatureModule {
67    @Binds
68    abstract fun bindsFeature(impl: FeatureImpl): Feature
69}
70```
71
72If you have a class that you want to make injectable that has can not
73be easily constructed by Dagger, write a `@Provides` method for it:
74
75```kotlin
76@Module
77abstract class FeatureModule {
78    @Module
79    companion object {
80        @Provides
81        fun providesFeature(ctx: Context): Feature {
82            return FeatureImpl.constructFromContext(ctx)
83        }
84    }
85}
86```
87
88### Module Organization
89
90Please define your modules on _at least_ per-package level. If the scope of a
91package grows to encompass a great number of features, create per-feature
92modules.
93
94**Do not create catch-all modules.** Those quickly grow unwieldy and
95unmaintainable. Any that exist today should be refactored into obsolescence.
96
97You can then include your module in one of three places:
98
991) Within another module that depends on it. Ideally, this creates a clean
100   dependency graph between features and utilities.
1012) For features that should exist in all versions of SystemUI (AOSP and
102   any variants), include the module in
103   [SystemUIModule.java](../src/com/android/systemui/dagger/SystemUIModule.java).
1043) For features that should exist only in AOSP, include the module in
105   [ReferenceSystemUIModule.java](../src/com/android/systemui/dagger/ReferenceSystemUIModule.java).
106   Similarly, if you are working on a custom version of SystemUI and have code
107   specific to your version, include it in a module specific to your version.
108
109### Using injection with Fragments
110
111Fragments are created as part of the FragmentManager, so injectable Fragments need to be registered
112so the manager knows how to create them. This is done via
113[FragmentService#addFragmentInstantiationProvider](../src/com/android/systemui/fragments/FragmentService.java).
114Pass it the class of your fragment and a `Provider` for your fragment at some time before your
115Fragment is accessed.
116
117When you need to create your fragment (i.e. for the add or replace transaction),
118then the FragmentHostManager can do this for you.
119
120```java
121FragmentHostManager.get(view).create(NavigationBarFragment.class);
122```
123
124## Updating Dagger2
125
126We depend on the Dagger source found in external/dagger2. We should automatically pick up on updates
127when that repository is updated.
128
129## TODO List
130
131 - Eliminate usages of Dependency#get: http://b/hotlists/3940788
132