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 they need to be 112setup so the manager knows how to create them. To do that, add a method 113to com.android.systemui.fragments.FragmentService$FragmentCreator that 114returns your fragment class. That is all that is required, once the method 115exists, FragmentService will automatically pick it up and use injection 116whenever your fragment needs to be created. 117 118```java 119public interface FragmentCreator { 120 NavigationBarFragment createNavigationBar(); 121} 122``` 123 124If you need to create your fragment (i.e. for the add or replace transaction), 125then the FragmentHostManager can do this for you. 126 127```java 128FragmentHostManager.get(view).create(NavigationBarFragment.class); 129``` 130 131## Updating Dagger2 132 133We depend on the Dagger source found in external/dagger2. We should automatically pick up on updates 134when that repository is updated. 135 136## TODO List 137 138 - Eliminate usages of Dependency#get: http://b/hotlists/3940788 139