Sharper Better Faster Dagger ‡ - Droidcon SF

130
SHARPER BETTER FASTER DAGGER @jrodbx @piwai

Transcript of Sharper Better Faster Dagger ‡ - Droidcon SF

Page 1: Sharper Better Faster Dagger ‡ - Droidcon SF

SHARPER BETTER FASTER DAGGER‡

@jrodbx @piwai

Page 2: Sharper Better Faster Dagger ‡ - Droidcon SF

SHARPER BETTER FASTER DAGGER‡

Page 3: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 4: Sharper Better Faster Dagger ‡ - Droidcon SF

// compile 'com.squareup.dagger:dagger:1.2.2'// apt 'com.squareup.dagger:dagger-compiler:1.2.2'compile 'com.google.dagger:dagger:2.0.2'apt 'com.google.dagger:dagger-compiler:2.0.2'provided 'javax.annotation:jsr250-api:1.0'

Page 5: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 6: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module( injects = { MainActivity.class }, addsTo = AppModule.class) public final class ApiModule { @Provides GithubService provideGithubService(Retrofit retrofit) { return retrofit.create(GithubService.class); } @Provides Retrofit provideRetrofit(@Endpoint String url) { return new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .build(); } }

Page 7: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module( injects = { MainActivity.class }, addsTo = AppModule.class) public final class ApiModule { @Provides GithubService provideGithubService(Retrofit retrofit) { return retrofit.create(GithubService.class); } @Provides Retrofit provideRetrofit(@Endpoint String url) { return new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .build(); }}

Page 8: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module( injects = { MainActivity.class }, addsTo = AppModule.class) public final class ApiModule { @Provides GithubService provideGithubService(Retrofit retrofit) { return retrofit.create(GithubService.class); } @Provides Retrofit provideRetrofit(@Endpoint String url) { return new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .build(); }}

Page 9: Sharper Better Faster Dagger ‡ - Droidcon SF

public class MainActivity extends Activity { @Inject GithubService githubService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);

ObjectGraph graph = getObjectGraph(); objectGraph.inject(this);

Page 10: Sharper Better Faster Dagger ‡ - Droidcon SF

public class MainActivity extends Activity { @Inject GithubService githubService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);

ObjectGraph graph = getObjectGraph(); objectGraph.inject(this);

Page 11: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module( injects = { MainActivity.class }, addsTo = AppModule.class) public final class ApiModule { @Provides GithubService provideGithubService(Retrofit retrofit) { return retrofit.create(GithubService.class); } @Provides Retrofit provideRetrofit(@Endpoint String url) { return new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .build(); }}

Page 12: Sharper Better Faster Dagger ‡ - Droidcon SF

@Modulepublic final class ApiModule { @Provides GithubService provideGithubService(Retrofit retrofit) { return retrofit.create(GithubService.class); } @Provides Retrofit provideRetrofit(@Endpoint String url) { return new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .build(); }}

Page 13: Sharper Better Faster Dagger ‡ - Droidcon SF

@Component( modules = ApiModule.class) public interface ApiComponent { Foo getFoo(); void inject(MainActivity activity); }

Page 14: Sharper Better Faster Dagger ‡ - Droidcon SF

@Component( modules = ApiModule.class) public interface ApiComponent { Foo getFoo(); void inject(MainActivity activity); }

Page 15: Sharper Better Faster Dagger ‡ - Droidcon SF

public class MainActivity extends Activity { @Inject GithubService githubService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ApiComponent apiComponent = DaggerApiComponent.builder().build(); apiComponent.inject(this); …

Page 16: Sharper Better Faster Dagger ‡ - Droidcon SF

public class MainActivity extends Activity { @Inject GithubService githubService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ApiComponent apiComponent = DaggerApiComponent.builder().build(); apiComponent.inject(this); …

Page 17: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module class AndroidModule {…}

@Module class HttpModule {…}

@Module class ApiModule {…}

Page 18: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module class AndroidModule {…}

@Module class HttpModule {…}

@Module class ApiModule {…}@Module class LoggedInModule {…}

@Module class PaymentModule {…}

@Module class TransactionLedgerModule {…}

Page 19: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 20: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 21: Sharper Better Faster Dagger ‡ - Droidcon SF

@Provides @Inject@Module

Page 22: Sharper Better Faster Dagger ‡ - Droidcon SF

@Provides @Inject@Module

@Provides2 @Inject2@Module2

Page 23: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph objectGraph = ObjectGraph.create(AppModule.class);

Page 24: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module public class AppModule { // ... @Provides OkHttpClient provideOkHttpClient() { return new OkHttpClient(); } @Provides Client provideRetrofitClient(OkHttpClient client) { return new OkClient(client); } // ...}

Page 25: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module public class AppModule { // ... @Provides OkHttpClient provideOkHttpClient() { return new OkHttpClient(); } @Provides Client provideRetrofitClient(OkHttpClient client) { return new OkClient(client); } // ...}

@Module2 public class AppModule2 {}

Page 26: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module public class AppModule { // ...}

@Module2 public class AppModule2 { @Provides2 OkHttpClient provideOkHttpClient() { return new OkHttpClient(); } @Provides2 Client provideRetrofitClient(OkHttpClient client) { return new OkClient(client); } }

Page 27: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module2 public class AppModule2 { @Provides2 OkHttpClient provideOkHttpClient() { return new OkHttpClient(); } @Provides2 Client provideRetrofitClient(OkHttpClient client) { return new OkClient(client); } }

@Component(modules = AppModule2.class) public interface AppComponent {}

Page 28: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module2 public class AppModule2 { @Provides2 OkHttpClient provideOkHttpClient() { return new OkHttpClient(); } @Provides2 Client provideRetrofitClient(OkHttpClient client) { return new OkClient(client); } }

@Component(modules = AppModule2.class)public interface AppComponent { Client retrofitClient(); OkHttpClient okHttpClient(); }

Page 29: Sharper Better Faster Dagger ‡ - Droidcon SF

@Component(modules = AppModule2.class) public interface AppComponent { AppComponentFacade dagger2Facade(); }

@Subcomponentpublic interface AppComponentFacade { Client retrofitClient(); OkHttpClient okHttpClient(); }

Page 30: Sharper Better Faster Dagger ‡ - Droidcon SF

@Subcomponentpublic interface AppComponentFacade { Client retrofitClient(); OkHttpClient okHttpClient();}

@Modulepublic class BridgeModule { private final AppComponentFacade facade; public BridgeModule(AppComponentFacade facade) { this.facade = facade; } @Provides Client retrofitClient() { return facade.retrofitClient(); } @Provides OkHttpClient okHttpClient() { return facade.okHttpClient(); } }

Page 31: Sharper Better Faster Dagger ‡ - Droidcon SF

@Subcomponentpublic interface AppComponentFacade { Client retrofitClient(); OkHttpClient okHttpClient();}

@Modulepublic class BridgeModule implements AppComponentFacade { private final AppComponentFacade facade; public BridgeModule(AppComponentFacade facade) { this.facade = facade; } @Override @Provides public Client retrofitClient() { return facade.retrofitClient(); } @Override @Provides public OkHttpClient okHttpClient() { return facade.okHttpClient(); }}

Page 32: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph objectGraph = ObjectGraph.create(AppModule.class);

Page 33: Sharper Better Faster Dagger ‡ - Droidcon SF

AppComponent component = DaggerAppComponent.builder().create();

ObjectGraph objectGraph = ObjectGraph.create(AppModule.class);

Page 34: Sharper Better Faster Dagger ‡ - Droidcon SF

AppComponent component = DaggerAppComponent.builder().create();AppComponentFacade facade = component.dagger2Facade();

ObjectGraph objectGraph = ObjectGraph.create(AppModule.class);

Page 35: Sharper Better Faster Dagger ‡ - Droidcon SF

AppComponent component = DaggerAppComponent.builder().create();AppComponentFacade facade = component.dagger2Facade();BridgeModule bridge = new BridgeModule(facade); ObjectGraph objectGraph = ObjectGraph.create(AppModule.class);

Page 36: Sharper Better Faster Dagger ‡ - Droidcon SF

AppComponent component = DaggerAppComponent.builder().create();AppComponentFacade facade = component.dagger2Facade();BridgeModule bridge = new BridgeModule(facade);ObjectGraph objectGraph = ObjectGraph.create(bridge, AppModule.class);

Page 37: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module2 public class AppModule2 { @Provides2 OkHttpClient provideOkHttpClient() { return new OkHttpClient(); } @Provides2 Client provideRetrofitClient(OkHttpClient client) { return new OkClient(client); } }

Page 38: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module2public class AppModule2 { @Provides2 OkHttpClient provideOkHttpClient(HostnameVerifier verifier) { OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setHostnameVerifier(verifier); return okHttpClient; } @Provides2 Client provideRetrofitClient(OkHttpClient client) { return new OkClient(client); }}

Page 39: Sharper Better Faster Dagger ‡ - Droidcon SF

@Modulepublic class AppModule { // ...}

Page 40: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module(injects = HostnameVerifier.class) public class AppModule { // ...}

Page 41: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module(injects = HostnameVerifier.class)public class AppModule { // ...}

@Module2public class GoldenGateModule { private ObjectGraph objectGraph; @Provides2 public HostnameVerifier provideHostnameVerifier() { return objectGraph.get(HostnameVerifier.class); } public void setObjectGraph(ObjectGraph objectGraph) { this.objectGraph = objectGraph; } }

Page 42: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module2public class GoldenGateModule { private ObjectGraph objectGraph; @Provides2 public HostnameVerifier provideHostnameVerifier() { return objectGraph.get(HostnameVerifier.class); } public void setObjectGraph(ObjectGraph objectGraph) { this.objectGraph = objectGraph; }}

@Module2 public class AppModule2 { // ...}

Page 43: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module2public class GoldenGateModule { private ObjectGraph objectGraph; @Provides2 public HostnameVerifier provideHostnameVerifier() { return objectGraph.get(HostnameVerifier.class); } public void setObjectGraph(ObjectGraph objectGraph) { this.objectGraph = objectGraph; }}

@Module2(includes = GoldenGateModule.class) public class AppModule2 { // ...}

Page 44: Sharper Better Faster Dagger ‡ - Droidcon SF

AppComponent component = DaggerAppComponent.builder().create(); AppComponentFacade facade = component.dagger2Facade(); BridgeModule bridge = new BridgeModule(facade); ObjectGraph objectGraph = ObjectGraph.create(bridge, AppModule.class);

Page 45: Sharper Better Faster Dagger ‡ - Droidcon SF

GoldenGateModule goldenGateModule = new GoldenGateModule(); AppComponent component = DaggerAppComponent.builder().create();AppComponentFacade facade = component.dagger2Facade();BridgeModule bridge = new BridgeModule(facade);ObjectGraph objectGraph = ObjectGraph.create(bridge, AppModule.class);

Page 46: Sharper Better Faster Dagger ‡ - Droidcon SF

GoldenGateModule goldenGateModule = new GoldenGateModule();AppComponent component = DaggerAppComponent.builder() .goldenGateModule(goldenGateModule) .create(); AppComponentFacade facade = component.dagger2Facade();BridgeModule bridge = new BridgeModule(facade);ObjectGraph objectGraph = ObjectGraph.create(bridge, AppModule.class);

Page 47: Sharper Better Faster Dagger ‡ - Droidcon SF

GoldenGateModule goldenGateModule = new GoldenGateModule();AppComponent component = DaggerAppComponent.builder() .goldenGateModule(goldenGateModule) .create();AppComponentFacade facade = component.dagger2Facade();BridgeModule bridge = new BridgeModule(facade);ObjectGraph objectGraph = ObjectGraph.create(bridge, AppModule.class);goldenGateModule.setObjectGraph(objectGraph);

Page 48: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 49: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 50: Sharper Better Faster Dagger ‡ - Droidcon SF

Guice

Dagger

Dagger2

better than Spring…?

improved linking + instance creation

improved linking more (1x per graph)

Page 51: Sharper Better Faster Dagger ‡ - Droidcon SF

@Override public ObjectGraph plus(Object... modules) { linkEverything(); return makeGraph(this, plugin, modules); }

Page 52: Sharper Better Faster Dagger ‡ - Droidcon SF

@Override public ObjectGraph plus(Object... modules) { linkEverything(); return makeGraph(this, plugin, modules);}

private Map<String, Binding<?>> linkEverything() { … return linker.linkAll(); }

public Map<String, Binding<?>> linkAll() { … linkRequested(); return Collections.unmodifiableMap(bindings); }

Page 53: Sharper Better Faster Dagger ‡ - Droidcon SF

public void linkRequested() { … while ((binding = toLink.poll()) != null) { if (binding instanceof DeferredBinding) { … = createBinding(…, deferred.classLoader, …); } }}

private Binding<?> createBinding(…, ClassLoader classLoader, …) { … … = instantiate(className.concat(INJECT_ADAPTER_SUFFIX), classLoader); … }

protected <T> T instantiate(String name, ClassLoader classLoader) { Class<?> generatedClass = loadClass(classLoader, name); if (generatedClass == Void.class) return null; return (T) generatedClass.newInstance(); }

Page 54: Sharper Better Faster Dagger ‡ - Droidcon SF

public void linkRequested() { … while ((binding = toLink.poll()) != null) { if (binding instanceof DeferredBinding) { … = createBinding(…, deferred.classLoader, …); } }}

private Binding<?> createBinding(…, ClassLoader classLoader, …) { … … = instantiate(className.concat(INJECT_ADAPTER_SUFFIX), classLoader); … }

protected <T> T instantiate(String name, ClassLoader classLoader) { Class<?> generatedClass = loadClass(classLoader, name); if (generatedClass == Void.class) return null; return (T) generatedClass.newInstance(); }

Page 55: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 56: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module class DripCoffeeModule { @Provides static Heater provideHeater(Executor executor) { return new CpuHeater(executor); } }

[ERROR] COMPILATION ERROR : [ERROR] error: java.util.concurrent.Executor cannot be provided without an @Provides-annotated method.

Page 57: Sharper Better Faster Dagger ‡ - Droidcon SF

Scoping!

Page 58: Sharper Better Faster Dagger ‡ - Droidcon SF

public class TransactionHandler { private final Analytics analytics; private final TaxCache taxCache; private Payment paymentInFlight; private Order order; @Inject TransactionHandler(Analytics analytics, TaxCache taxCache) { this.analytics = analytics; this.taxCache = taxCache; } // ...}

Page 59: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 60: Sharper Better Faster Dagger ‡ - Droidcon SF

public class TransactionHandler { private final Analytics analytics; private final TaxCache taxCache; private Payment paymentInFlight; private Order order; @Inject TransactionHandler(Analytics analytics, TaxCache taxCache) { this.analytics = analytics; this.taxCache = taxCache; } // ...}

Page 61: Sharper Better Faster Dagger ‡ - Droidcon SF

@Singleton public class TransactionHandler { private final Analytics analytics; private final TaxCache taxCache; private Payment paymentInFlight; private Order order; @Inject TransactionHandler(Analytics analytics, TaxCache taxCache) { this.analytics = analytics; this.taxCache = taxCache; } // ...}

Page 62: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 63: Sharper Better Faster Dagger ‡ - Droidcon SF

public class Linker { final Map<Class<?>, Binding<?>> bindings = new HashMap<>(); <T> Binding<T> requestBinding(Class<T> key) { return (Binding<T>) bindings.get(key); } }

Page 64: Sharper Better Faster Dagger ‡ - Droidcon SF

public class Linker { final Map<Class<?>, Binding<?>> bindings = new HashMap<>(); <T> Binding<T> requestBinding(Class<T> key) { return (Binding<T>) bindings.get(key); }}

Page 65: Sharper Better Faster Dagger ‡ - Droidcon SF

public abstract class Binding<T> { final boolean singleton; protected Binding(boolean singleton) { this.singleton = singleton; } abstract void attach(Linker linker); abstract T get(); }

Page 66: Sharper Better Faster Dagger ‡ - Droidcon SF

public abstract class Binding<T> { final boolean singleton; protected Binding(boolean singleton) { this.singleton = singleton; } abstract void attach(Linker linker); abstract T get();}

Page 67: Sharper Better Faster Dagger ‡ - Droidcon SF

public abstract class Binding<T> { final boolean singleton; protected Binding(boolean singleton) { this.singleton = singleton; } abstract void attach(Linker linker); abstract T get();}

Page 68: Sharper Better Faster Dagger ‡ - Droidcon SF

public abstract class Binding<T> { final boolean singleton; protected Binding(boolean singleton) { this.singleton = singleton; } abstract void attach(Linker linker); abstract T get(); }

Page 69: Sharper Better Faster Dagger ‡ - Droidcon SF

public class TransactionHandler$$InjectAdapter extends Binding<TransactionHandler> { private Binding<TaxCache> taxCache; private Binding<Analytics> analytics; public TransactionHandler$$InjectAdapter() { super(IS_SINGLETON); } @Override public void attach(Linker linker) { analytics = linker.requestBinding(Analytics.class); taxCache = linker.requestBinding(TaxCache.class); } @Override public TransactionHandler get() { return new TransactionHandler(analytics.get(), taxCache.get()); }}

Page 70: Sharper Better Faster Dagger ‡ - Droidcon SF

public class TransactionHandler$$InjectAdapter extends Binding<TransactionHandler> { private Binding<TaxCache> taxCache; private Binding<Analytics> analytics; public TransactionHandler$$InjectAdapter() { super(IS_SINGLETON); } @Override public void attach(Linker linker) { analytics = linker.requestBinding(Analytics.class); taxCache = linker.requestBinding(TaxCache.class); } @Override public TransactionHandler get() { return new TransactionHandler(analytics.get(), taxCache.get()); }}

Page 71: Sharper Better Faster Dagger ‡ - Droidcon SF

public class TransactionHandler$$InjectAdapter extends Binding<TransactionHandler> { private Binding<TaxCache> taxCache; private Binding<Analytics> analytics; public TransactionHandler$$InjectAdapter() { super(IS_SINGLETON); } @Override public void attach(Linker linker) { analytics = linker.requestBinding(Analytics.class); taxCache = linker.requestBinding(TaxCache.class); } @Override public TransactionHandler get() { return new TransactionHandler(analytics.get(), taxCache.get()); } }

Page 72: Sharper Better Faster Dagger ‡ - Droidcon SF

public class SingletonBinding<T> extends Binding<T> { final Binding<T> delegate; T instance; SingletonBinding(Binding<T> delegate) { this.delegate = delegate; } @Override void attach(Linker linker) { delegate.attach(linker); } @Override T get() { if (instance == null) { instance = delegate.get(); } return instance; } }

Page 73: Sharper Better Faster Dagger ‡ - Droidcon SF

public class SingletonBinding<T> extends Binding<T> { final Binding<T> delegate; T instance; SingletonBinding(Binding<T> delegate) { this.delegate = delegate; } @Override void attach(Linker linker) { delegate.attach(linker); } @Override T get() { if (instance == null) { instance = delegate.get(); } return instance; } }

Page 74: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph Linker SingletonBinding

Binding

TransactionHandler

Binding

Binding

Page 75: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 76: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 77: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph TransactionHandler

Page 78: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph TransactionHandler

Page 79: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph TransactionHandler

PrinterHandler

Page 80: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph TransactionHandler

PrinterHandlerObjectGraph

Page 81: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph

TransactionHandlerPrinterHandler

ObjectGraph

ObjectGraph AppSingleton

Page 82: Sharper Better Faster Dagger ‡ - Droidcon SF

TransactionPrintScreen

App

Page 83: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 84: Sharper Better Faster Dagger ‡ - Droidcon SF

@Singleton public class TransactionHandler { private final Analytics analytics; private final TaxCache taxCache; private Payment paymentInFlight; private Order order; @Inject TransactionHandler(Analytics analytics, TaxCache taxCache) { this.analytics = analytics; this.taxCache = taxCache; } // ...}

Page 85: Sharper Better Faster Dagger ‡ - Droidcon SF

public class TransactionFlow { private final TransactionHandler transactionHandler; @Inject TransactionFlow(TransactionHandler transactionHandler) { this.transactionHandler = transactionHandler; } // ...}

Page 86: Sharper Better Faster Dagger ‡ - Droidcon SF

public class TransactionFlow { private final TransactionHandler transactionHandler; @Inject TransactionFlow(TransactionHandler transactionHandler) { this.transactionHandler = transactionHandler; } // ...}

public class TransactionFlowLayout extends FrameLayout { public TransactionFlowLayout(Context context, AttributeSet attrs) { super(context, attrs); TransactionFlow transactionFlow = ???; // ... } }

Page 87: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module(injects = TransactionFlow.class) class TransactionModule {}

Page 88: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph transactionGraph = appGraph.plus(TransactionModule.class);

@Module(injects = TransactionFlow.class)class TransactionModule {}

Page 89: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph transactionGraph = appGraph.plus(TransactionModule.class);

@Module(injects = TransactionFlow.class) class TransactionModule {}

public class TransactionFlowLayout extends FrameLayout { public TransactionFlowLayout(Context context, AttributeSet attrs) { super(context, attrs); ObjectGraph graph = getTransactionGraph(); TransactionFlow transactionFlow = graph.get(TransactionFlow.class); // ... }}

Page 90: Sharper Better Faster Dagger ‡ - Droidcon SF

public class CartPresenter { private final TransactionHandler transactionHandler; @Inject CartPresenter(TransactionHandler transactionHandler) { this.transactionHandler = transactionHandler; } // ...}

Page 91: Sharper Better Faster Dagger ‡ - Droidcon SF

public class CartPresenter { private final TransactionHandler transactionHandler; @Inject CartPresenter(TransactionHandler transactionHandler) { this.transactionHandler = transactionHandler; } // ...}

public class CartView extends CoordinatorLayout { public CartView(Context context, AttributeSet attrs) { super(context, attrs); ObjectGraph cartGraph = getCartGraph(); CartPresenter cartPresenter = cartGraph.get(CartPresenter.class); // ... } }

Page 92: Sharper Better Faster Dagger ‡ - Droidcon SF

public class CartPresenter { private final TransactionHandler transactionHandler; @Inject CartPresenter(TransactionHandler transactionHandler) { this.transactionHandler = transactionHandler; } // ...}

public class CartView extends CoordinatorLayout { public CartView(Context context, AttributeSet attrs) { super(context, attrs); ObjectGraph cartGraph = getCartGraph(); CartPresenter cartPresenter = cartGraph.get(CartPresenter.class); // ... }}

Page 93: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph transactionGraph = appGraph.plus(TransactionModule.class); ObjectGraph cartGraph = transactionGraph.plus(CartScreenModule.class);

Page 94: Sharper Better Faster Dagger ‡ - Droidcon SF

ObjectGraph transactionGraph = appGraph.plus(TransactionModule.class); ObjectGraph cartGraph = transactionGraph.plus(CartScreenModule.class);

@Module(injects = TransactionFlow.class) class TransactionModule {}

@Module(injects = CartPresenter.class) class CartScreenModule {}

Page 95: Sharper Better Faster Dagger ‡ - Droidcon SF

public class ObjectGraph { Linker linker; public <T> T get(Class<T> key) { Binding<T> binding = linker.requestBinding(key); return binding.get(); } }

Page 96: Sharper Better Faster Dagger ‡ - Droidcon SF

public class ObjectGraph { Linker linker; ObjectGraph parentGraph; public <T> T get(Class<T> key) { if (parentGraph != null) { T instance = parentGraph.get(key); if (instance != null) { return instance; } } Binding<T> binding = linker.requestBinding(key); return binding.get(); }}

Page 97: Sharper Better Faster Dagger ‡ - Droidcon SF

public class Linker { final Map<Class<?>, Binding<?>> bindings = new HashMap<>(); <T> Binding<T> requestBinding(Class<T> key) { return (Binding<T>) bindings.get(key); } }

Page 98: Sharper Better Faster Dagger ‡ - Droidcon SF

public class Linker { final Map<Class<?>, Binding<?>> bindings = new HashMap<>(); <T> Binding<T> requestBinding(Class<T> key) { Binding<T> binding = (Binding<T>) bindings.get(key); if (binding == null) { binding = loadGeneratedBinding(key); if (binding.singleton) { binding = new SingletonBinding<>(binding); } bindings.put(key, binding); } return binding; }}

Page 99: Sharper Better Faster Dagger ‡ - Droidcon SF

Binding

Binding

CartPresenter

TransactionFlow

Cart screen graph

Transaction graphSingletonBinding

TransactionHandler

Page 100: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 101: Sharper Better Faster Dagger ‡ - Droidcon SF

Binding

Binding

CartPresenter

TransactionFlow

Cart screen graph

Transaction graphSingletonBinding

TransactionHandler

Page 102: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 103: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 104: Sharper Better Faster Dagger ‡ - Droidcon SF

com.squareup.Transaction binding found in scopes marked with '*' (if any).  SCOPE RegisterRootScope  +-SCOPE com.squareup.dagger.LoggedIn  | `-SCOPE com.squareup.ui.root.RootActivity  | `-SCOPE * com.squareup.ui.root.RootFlow  | `-SCOPE com.squareup.ui.seller.SellerFlow  | `-SCOPE com.squareup.ui.home.HomeScreen  `-SCOPE com.squareup.ui.PaymentActivity

Page 105: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module(injects = TransactionFlow.class) class TransactionModule {}

ObjectGraph transactionGraph = appGraph.plus(TransactionModule.class);

Page 106: Sharper Better Faster Dagger ‡ - Droidcon SF

@Module(injects = TransactionFlow.class)class TransactionModule { @Provides @Singleton TransactionHandler transactionHandler(Analytics analytics, TaxCache taxCache) { return new TransactionHandler(analytics, taxCache); } }

ObjectGraph transactionGraph = appGraph.plus(TransactionModule.class);

Page 107: Sharper Better Faster Dagger ‡ - Droidcon SF

Page 108: Sharper Better Faster Dagger ‡ - Droidcon SF

@Singleton public class TransactionHandler {...}

@Module(injects = TransactionFlow.class) public class TransactionModule {}

Page 109: Sharper Better Faster Dagger ‡ - Droidcon SF

@Singleton public class TransactionHandler {...}

@Module(injects = TransactionFlow.class)public class TransactionModule {}

@Scope public @interface SingleInTransaction {}

Page 110: Sharper Better Faster Dagger ‡ - Droidcon SF

@SingleInTransaction public class TransactionHandler {...}

@Module(injects = TransactionFlow.class)public class TransactionModule {}

@Scope public @interface SingleInTransaction {}

Page 111: Sharper Better Faster Dagger ‡ - Droidcon SF

@SingleInTransaction public class TransactionHandler {...}

@Module(injects = TransactionFlow.class)public class TransactionModule {}

@Scope public @interface SingleInTransaction {}

@Component interface TransactionComponent {}

Page 112: Sharper Better Faster Dagger ‡ - Droidcon SF

@SingleInTransaction public class TransactionHandler {...}

@Module(injects = TransactionFlow.class)public class TransactionModule {}

@Scope public @interface SingleInTransaction {}

@SingleInTransaction@Component interface TransactionComponent {}

Page 113: Sharper Better Faster Dagger ‡ - Droidcon SF

@SingleInTransaction public class TransactionHandler {...}

@Module(injects = TransactionFlow.class) public class TransactionModule {}

@Scope public @interface SingleInTransaction {}

@SingleInTransaction@Component(modules = TransactionModule.class) interface TransactionComponent {}

Page 114: Sharper Better Faster Dagger ‡ - Droidcon SF

@SingleInTransaction public class TransactionHandler {...}

@Modulepublic class TransactionModule {}

@Scope public @interface SingleInTransaction {}

@SingleInTransaction@Component(modules = TransactionModule.class) interface TransactionComponent { TransactionFlow transactionFlow(); }

Page 115: Sharper Better Faster Dagger ‡ - Droidcon SF

@SingleInTransaction public class TransactionHandler {...}

@Modulepublic class TransactionModule {}

@Scope public @interface SingleInTransaction {}

@SingleInTransaction@Component(modules = TransactionModule.class) interface TransactionComponent { TransactionFlow transactionFlow();}

Page 116: Sharper Better Faster Dagger ‡ - Droidcon SF

@SingleInTransaction public class TransactionHandler {...}

@Modulepublic class TransactionModule {}

@Scope public @interface SingleIn { Class<?> value(); }

@SingleInTransaction@Component(modules = TransactionModule.class) interface TransactionComponent { TransactionFlow transactionFlow();}

Page 117: Sharper Better Faster Dagger ‡ - Droidcon SF

@SingleIn(TransactionComponent.class) public class TransactionHandler {...}

@Modulepublic class TransactionModule {}

@Scope public @interface SingleIn { Class<?> value(); }

@SingleInTransaction@Component(modules = TransactionModule.class) interface TransactionComponent { TransactionFlow transactionFlow();}

Page 118: Sharper Better Faster Dagger ‡ - Droidcon SF

@SingleIn(TransactionComponent.class) public class TransactionHandler {...}

@Modulepublic class TransactionModule {}

@Scope public @interface SingleIn { Class<?> value(); }

@SingleIn(TransactionComponent.class) @Component(modules = TransactionModule.class) interface TransactionComponent { TransactionFlow transactionFlow();}

Page 119: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 120: Sharper Better Faster Dagger ‡ - Droidcon SF

Transaction flow graphPrint screen graph

App graph

Cart screen graph

Page 121: Sharper Better Faster Dagger ‡ - Droidcon SF

Transaction flow graphPrint screen graph

App graph

Cart screen graph

Page 122: Sharper Better Faster Dagger ‡ - Droidcon SF

Transaction flow graphPrint screen graph

App graph

Cart screen graph

proxy graph

Page 123: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 124: Sharper Better Faster Dagger ‡ - Droidcon SF

Transaction flow graphPrint screen graph

App graph

Cart screen graph

Page 125: Sharper Better Faster Dagger ‡ - Droidcon SF

Transaction flow graphPrint screen graph

App graph

Cart screen graph

Page 126: Sharper Better Faster Dagger ‡ - Droidcon SF

@Componentpublic interface CartScreenComponent { CartPresenter cartPresenter(); }

Page 127: Sharper Better Faster Dagger ‡ - Droidcon SF

@Component(modules = CartScreenModule.class) public interface CartScreenComponent { CartPresenter cartPresenter();}

Page 128: Sharper Better Faster Dagger ‡ - Droidcon SF

public interface CartScreenDependencies { TransactionHandler transactionHandler(); }

@Component(modules = CartScreenModule.class, dependencies = CartScreenDependencies.class) public interface CartScreenComponent { CartPresenter cartPresenter();}

Page 129: Sharper Better Faster Dagger ‡ - Droidcon SF
Page 130: Sharper Better Faster Dagger ‡ - Droidcon SF

@jrodbx @piwai