Sharper Better Faster Dagger ‡ - Droidcon SF

Post on 20-Feb-2017

7.088 views 2 download

Transcript of Sharper Better Faster Dagger ‡ - Droidcon SF

SHARPER BETTER FASTER DAGGER‡

@jrodbx @piwai

SHARPER BETTER FASTER DAGGER‡

// 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'

@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(); } }

@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(); }}

@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(); }}

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);

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);

@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(); }}

@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(); }}

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

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

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); …

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); …

@Module class AndroidModule {…}

@Module class HttpModule {…}

@Module class ApiModule {…}

@Module class AndroidModule {…}

@Module class HttpModule {…}

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

@Module class PaymentModule {…}

@Module class TransactionLedgerModule {…}

@Provides @Inject@Module

@Provides @Inject@Module

@Provides2 @Inject2@Module2

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

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

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

@Module2 public class AppModule2 {}

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

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

@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 {}

@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(); }

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

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

@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(); } }

@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(); }}

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

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

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

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

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

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

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

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

@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); }}

@Modulepublic class AppModule { // ...}

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

@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; } }

@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 { // ...}

@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 { // ...}

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

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);

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 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);

Guice

Dagger

Dagger2

better than Spring…?

improved linking + instance creation

improved linking more (1x per graph)

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

@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); }

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(); }

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(); }

@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.

Scoping!

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; } // ...}

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; } // ...}

@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; } // ...}

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

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

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

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

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

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

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()); }}

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()); }}

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()); } }

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; } }

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; } }

ObjectGraph Linker SingletonBinding

Binding

TransactionHandler

Binding

Binding

ObjectGraph TransactionHandler

ObjectGraph TransactionHandler

ObjectGraph TransactionHandler

PrinterHandler

ObjectGraph TransactionHandler

PrinterHandlerObjectGraph

ObjectGraph

TransactionHandlerPrinterHandler

ObjectGraph

ObjectGraph AppSingleton

TransactionPrintScreen

App

@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; } // ...}

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

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 = ???; // ... } }

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

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

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

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); // ... }}

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

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); // ... } }

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); // ... }}

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

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

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

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

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

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(); }}

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

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; }}

Binding

Binding

CartPresenter

TransactionFlow

Cart screen graph

Transaction graphSingletonBinding

TransactionHandler

Binding

Binding

CartPresenter

TransactionFlow

Cart screen graph

Transaction graphSingletonBinding

TransactionHandler

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

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

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

@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);

@Singleton public class TransactionHandler {...}

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

@Singleton public class TransactionHandler {...}

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

@Scope public @interface SingleInTransaction {}

@SingleInTransaction public class TransactionHandler {...}

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

@Scope public @interface SingleInTransaction {}

@SingleInTransaction public class TransactionHandler {...}

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

@Scope public @interface SingleInTransaction {}

@Component interface TransactionComponent {}

@SingleInTransaction public class TransactionHandler {...}

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

@Scope public @interface SingleInTransaction {}

@SingleInTransaction@Component interface TransactionComponent {}

@SingleInTransaction public class TransactionHandler {...}

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

@Scope public @interface SingleInTransaction {}

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

@SingleInTransaction public class TransactionHandler {...}

@Modulepublic class TransactionModule {}

@Scope public @interface SingleInTransaction {}

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

@SingleInTransaction public class TransactionHandler {...}

@Modulepublic class TransactionModule {}

@Scope public @interface SingleInTransaction {}

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

@SingleInTransaction public class TransactionHandler {...}

@Modulepublic class TransactionModule {}

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

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

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

@Modulepublic class TransactionModule {}

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

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

@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();}

Transaction flow graphPrint screen graph

App graph

Cart screen graph

Transaction flow graphPrint screen graph

App graph

Cart screen graph

Transaction flow graphPrint screen graph

App graph

Cart screen graph

proxy graph

Transaction flow graphPrint screen graph

App graph

Cart screen graph

Transaction flow graphPrint screen graph

App graph

Cart screen graph

@Componentpublic interface CartScreenComponent { CartPresenter cartPresenter(); }

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

public interface CartScreenDependencies { TransactionHandler transactionHandler(); }

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

@jrodbx @piwai