Demystifying dependency Injection: Dagger and Toothpick

122
I come with knifes A story of Daggers and ToothpicksDroidcon Krakow 2016 Danny Preussler @PreusslerBerlin

Transcript of Demystifying dependency Injection: Dagger and Toothpick

Page 1: Demystifying dependency Injection: Dagger and Toothpick

I come with knifesA story of Daggers and Toothpicks…

Droidcon Krakow 2016Danny Preussler

@PreusslerBerlin

Page 2: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Once upon a time

Page 3: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

A single activity

Page 4: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class LonelyActivity extends Activity {

@Override protected void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.activity_main); }}

Page 5: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

needs to

Page 6: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

needs to support

Page 7: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

needs to supportTracking

Page 8: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

The journey to testability starts

Page 9: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Starring

Page 10: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Tracker as componentpublic interface Tracker {

void trackStarted();}

Page 11: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

GoogleAnalyticsTracker as Trackerpublic class GoogleAnalyticsTracker implements Tracker {

@Override public void trackStarted() { }}

Page 12: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

PrologThe Untestable

Page 13: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class LonelyActivity extends Activity {

private final Tracker tracker = new GoogleAnalyticsTracker();

@Override protected void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.activity_main); tracker.trackStarted(); }}

Page 14: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class LonelyActivity extends Activity {

private final Tracker tracker = new GoogleAnalyticsTracker();

@Override protected void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.activity_main); tracker.trackStarted(); }}

Page 15: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class LonelyActivity extends Activity {

private final Tracker tracker = new GoogleAnalyticsTracker();

@Override protected void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.activity_main); tracker.trackStarted(); }}

Not testable!

Page 16: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

A voice out of the dark:Inversion of Control!

Page 17: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

A voice out of the dark:Inversion of Control!

Page 18: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class LonelyActivity extends Activity {

private final Tracker tracker = new GoogleAnalyticsTracker();

@Override protected void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.activity_main); tracker.trackStarted(); }}

Page 19: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Act IThe Factory

Page 20: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class Dependencies {

static Dependencies instance = new Dependencies();

public static Dependencies getInstance() { return instance; }

public Tracker getTracker() { return new GoogleAnalyticsTracker(); }

Page 21: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class Dependencies {

static Dependencies instance = new Dependencies();

public static Dependencies getInstance() { return instance; }

public Tracker getTracker() { return new GoogleAnalyticsTracker(); }

Page 22: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class Dependencies {

static Dependencies instance = new Dependencies();

public static Dependencies getInstance() { return instance; }

public Tracker getTracker() { return new GoogleAnalyticsTracker(); }

Page 23: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

Tracker tracker = getInstance().getTracker();

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 24: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

Tracker tracker = getInstance().getTracker();

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 25: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Mock Tracker tracker;

@Beforepublic void setup() {… Dependencies.instance = mock(Dependencies.class); when(Dependencies.instance.getTracker())

.thenReturn(tracker);}

@Testpublic void should_track() { new SimpleActivity().onCreate(null); verify(tracker).trackStarted();}

Page 26: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Mock Tracker tracker;

@Beforepublic void setup() {… Dependencies.instance = mock(Dependencies.class); when(Dependencies.instance.getTracker())

.thenReturn(tracker);}

@Testpublic void should_track() { new SimpleActivity().onCreate(null); verify(tracker).trackStarted();}

Page 27: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Mock Tracker tracker;

@Beforepublic void setup() {… Dependencies.instance = mock(Dependencies.class); when(Dependencies.instance.getTracker())

.thenReturn(tracker);}

@Testpublic void should_track() { new SimpleActivity().onCreate(null); verify(tracker).trackStarted();}

Page 28: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

+/- Somehow testable- Not very dynamic

- Lots of code

Page 29: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Act IIThe Map

Page 30: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class Dependencies {

static Map<Class, Class> modules = new HashMap<>(); static { modules.put(

Tracker.class, new GoogleAnalyticsTracker());

}

public static <T> T get(Class<T> clzz) { return (T) modules.get(clzz); }}

Page 31: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class Dependencies {

static Map<Class, Class> modules = new HashMap<>(); static { modules.put(

Tracker.class, new GoogleAnalyticsTracker());

}

public static <T> T get(Class<T> clzz) { return (T) modules.get(clzz); }}

Page 32: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

Tracker tracker = getInstance().get(Tracker.class);

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 33: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

Tracker tracker = getInstance().get(Tracker.class);

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 34: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

+ Testable+ Dynamic

- Instances created at startup

Page 35: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Act IIIReflection(s)

Page 36: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class Dependencies {

private final static Map<Class, Class> modules = new HashMap<>();

static { modules.put(

Tracker.class, GoogleAnalyticsTracker.class);

}static <T> T get(Class<T> clzz) {…

Page 37: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class GoogleAnalyticsTracker implements Tracker {

GoogleAnalyticsTracker(Activity activity) {

...}

GoogleAnalyticsTracker(Application application) { ...}

GoogleAnalyticsTracker(Context context) { ...}...

?

Page 38: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class GoogleAnalyticsTracker implements Tracker {

GoogleAnalyticsTracker(Activity activity) {

...}

GoogleAnalyticsTracker(Application application) { ...}

@Inject GoogleAnalyticsTracker(Context context) { ...}...

Page 39: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

package javax.inject;

@Target({ METHOD, CONSTRUCTOR, FIELD })@Retention(RUNTIME)public @interface Inject {}

Page 40: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class Dependencies {

private final static Map<Class, Class> modules = new HashMap<>();

static { modules.put(

Tracker.class, GoogleAnalyticsTracker.class);

}static <T> T get(Class<T> clzz) {…

Page 41: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

static <T> T get(Class<T> clzz) {…

Constructor<?>[] constructors = clzz.getDeclaredConstructors();

for(Constructor ctr: constructors) {

Page 42: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

static <T> T get(Class<T> clzz) {…

Constructor<?>[] constructors = clzz.getDeclaredConstructors();

for(Constructor ctr: constructors) {

Page 43: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

...if(ctr.getDeclaredAnnotation(Inject.class) != null) { Class[] types = ctr.getParameterTypes(); Object[] params = new Object[types.length]; for (int i=1; i< params.length; i++) {

params[i] = get(types[i]); }

Page 44: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

if(ctr.getDeclaredAnnotation(Inject.class) != null) { Class[] types = ctr.getParameterTypes(); Object[] params = new Object[types.length]; for (int i=1; i< params.length; i++) {

params[i] = get(types[i]); }

Page 45: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

if(ctr.getDeclaredAnnotation(Inject.class) != null) { Class[] types = ctr.getParameterTypes(); Object[] params = new Object[types.length]; for (int i=1; i< params.length; i++) {

params[i] = get(types[i]); }

Page 46: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

... try { return (T) ctr.newInstance(params);

} catch (Exception e) { ...

}

Page 47: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

Tracker tracker = getInstance().get(Tracker.class);

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 48: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

Tracker tracker = getInstance().get(Tracker.class);

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 49: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

+ Testable+ Dynamic+ Flexible

Page 50: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Can we improve that?

Page 51: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

Tracker tracker = getInstance().get(Tracker.class);

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 52: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

Tracker tracker = getInstance().get(Tracker.class);

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 53: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

@Inject Tracker tracker;

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 54: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

@Inject Tracker tracker;

@Override protected void onCreate(Bundle state) { super.onCreate(state);

Dependencies.inject(this);... tracker.trackStarted(); }}

Page 55: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

static void inject(Object instance) {

Field[] fields = instance.getClass().getDeclaredFields();

for (Field f: fields) {

if (f.getDeclaredAnnotation(Inject.class) != null){ try { field.set(instance, get(f.getType())); } catch (IllegalAccessException e) {...}...

Page 56: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

static void inject(Object instance) {

Field[] fields = instance.getClass().getDeclaredFields();

for (Field f: fields) {

if (f.getDeclaredAnnotation(Inject.class) != null){ try { field.set(instance, get(f.getType())); } catch (IllegalAccessException e) {...}...

Page 57: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

static void inject(Object instance) {

Field[] fields = instance.getClass().getDeclaredFields();

for (Field f: fields) {

if (f.getDeclaredAnnotation(Inject.class) != null){ try { field.set(instance, get(f.getType())); } catch (IllegalAccessException e) {...}...

Page 58: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

static void inject(Object instance) {

Field[] fields = instance.getClass().getDeclaredFields();

for (Field f: fields) {

if (f.getDeclaredAnnotation(Inject.class) != null){ try { field.set(instance, get(f.getType())); } catch (IllegalAccessException e) {...}...

Page 59: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

OMG,We just built

Page 60: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

OMG,We just built

Guice!

Page 61: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

OMG,We just built RoboGuice!

Page 62: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

OMG,We just built RoboGuice!

Page 63: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Dependencies.getInstance;

class LonelyActivity extends Activity {

@Inject Tracker tracker;

@Override protected void onCreate(Bundle state) { super.onCreate(state);

Dependencies.inject(this);... tracker.trackStarted(); }}

Page 64: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

- Reflection is slow

Page 65: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

"Avoid dependency injection frameworks”

- Google developer.android.com/training/articles/memory.html#DependencyInjection

till early 2016

Page 66: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Act IVCompiler Magic

Page 67: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Annotation processing&

Code generation

Page 68: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Here comes Dagger as Hero

Page 69: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

The end!?

Page 70: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

In its first screen appearance:

Toothpick as unknown stranger

Page 71: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

“YOUR boilerplate sucks”

Page 72: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

“YOU don’t even know how to unit test!”

Page 73: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Fight!

Page 74: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

The module

Page 75: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Modulestatic class BaseModule {...

BaseModule(Application application) {... }

@Provides public Tracker provideTracker() { return new GoogleAnalyticsTracker(); }}

Page 76: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

class BaseModule extends Module {

public BaseModule(Application application) {

bind(Tracker.class) .to(GoogleAnalyticsTracker.class); ...

Page 77: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

The component

Page 78: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Component(modules = {BaseModule.class})interface AppComponent { void inject(LonelyActivity activity);}

Page 79: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

“WHAT component???”

Page 80: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Setup

Dagger 0 : 1 Toothpick

Page 81: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Usage

Page 82: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

class LonelyActivity extends Activity {

@Inject Tracker tracker;

@Override protected void onCreate(Bundle state) { super.onCreate(state);... tracker.trackStarted(); }}

Page 83: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

class MainApplication extends Application {

@Override public void onCreate() { super.onCreate();

DaggerDependencies_AppComponent .builder()

.baseModule( new BaseModule(this))

.build()

Page 84: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

class LonelyActivity extends Activity {

@Inject Tracker tracker;

@Override protected void onCreate(Bundle state) { super.onCreate(state);

getApplication().getComponent().inject(this); tracker.trackStarted(); }}

Page 85: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Scope scope = openScope("APPLICATION")

scope.installModules(new BaseModule(application));

Page 86: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

import static Toothpick.openScope;

class LonelyActivity extends Activity {

@Inject Tracker tracker;

@Override protected void onCreate(Bundle state) { super.onCreate(state); openScope("APPLICATION").inject(this); tracker.trackStarted(); }}

Page 87: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Usage

Dagger 1 : 2 Toothpick

Page 88: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Testing

Page 89: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Testing

Page 90: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Mock Tracker tracker;

class TestModule extends Dependencies.BaseModule {

TestModule() { super(mock(Application.class)); }

@Provides public Tracker provideTracker() { return tracker; } }}

Page 91: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Mock Tracker tracker;

class TestModule extends Dependencies.BaseModule {

TestModule() { super(mock(Application.class)); }

@Provides public Tracker provideTracker() { return tracker; } }}

Page 92: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Test public void should_track() { Application.set(

DaggerDependencies_AppComponent.builder().baseModule(

new TestModule()).build());

new LonelyActivity().onCreate(null); verify(tracker).trackStarted(); }...}

Page 93: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Test public void should_track() { Application.set(

DaggerDependencies_AppComponent.builder().baseModule(

new TestModule()).build());

new LonelyActivity().onCreate(null); verify(tracker).trackStarted(); }...}

Page 94: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Mock Tracker tracker;

@Rulepublic ToothPickRule toothPickRule =

new ToothPickRule(this, "APPLICATION_SCOPE");

@Testpublic void should_track() {

new LonelyActivity().onCreate(null); verify(tracker).trackStarted();}

Page 95: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Mock Tracker tracker;

@Rulepublic ToothPickRule toothPickRule =

new ToothPickRule(this, "APPLICATION_SCOPE");

@Testpublic void should_track() {

new LonelyActivity().onCreate(null); verify(tracker).trackStarted();}

Page 96: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Testing

Dagger 1 : 3 Toothpick

Page 97: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Scopes

Page 98: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Singleton

Page 99: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Scope@Retention(RUNTIME)public @interface ActivityScope {}

@ActivityScope@Subcomponent(modules = {ScopeModule.class})interface ScopeComponent { void inject(ScopeActivity activity);}

Page 100: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Modulestatic class ScopeModule {

private Activity activity;

public ScopeModule(Activity activity) { this.activity = activity; }

@Provides @ActivityScope public Activity provideActivity() { return activity; }}

Page 101: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

@Component(modules = {BaseModule.class})interface AppComponent { void inject(LonelyActivity activity); ScopeComponent plus(ScopeModule module);}

Page 102: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

“That’s Annotation Porn!”

Page 103: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class ScopeActivity extends Activity {

… private ScopeComponent scope;

@Override protected void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.activity_main); scope = createScope(this); scope.inject(this); … }

// call from fragments... public ScopeComponent getScope() { return scope; }}

Page 104: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

public class ScopeActivity extends Activity {

… private ScopeComponent scope;

@Override protected void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.activity_main); scope = createScope(this); scope.inject(this); … }

// call from fragments... public ScopeComponent getScope() { return scope; }}

Page 105: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

“Stop this madness!”

Page 106: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

class ScopeModule extends Module {

public ScopeModule(Activity activity) { bind(Activity.class).toInstance(activity); }

Page 107: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Scope scope = openScopes(”APPLICATION_SCOPE”,

activity.getClass().getName());

scope.installModules(new ScopeModule(activity));

Page 108: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Scope scope = openScopes(”APPLICATION_SCOPE”,

activity.getClass().getName());

scope.installModules(new ScopeModule(activity));

Page 109: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

closeScope(activity.getClass().getName());

Page 110: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Scopes

Dagger 1 : 4 Toothpick

Page 111: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Performance

Page 112: Demystifying dependency Injection: Dagger and Toothpick

1000 injections• Dagger 1: 33 ms

• Dagger 2: 31 ms

• Toothpick: 35 ms

6400 injections• Dagger 1: 45 ms

• Dagger 2: 42 ms

• Toothpick: 66 ms

Page 113: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Performance

Dagger 2 : 4 Toothpick

Page 114: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

And there is more:

SmoothieModule

Page 115: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Ease of use

Speed

Roboguice

Dagger

Toothpick

Page 116: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Dagger:+ compile safe+ feature rich+ performant

Page 117: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Dagger:-heavy weight- top down

- annotation porn- hard on unit tests

Page 118: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Toothpick:+ light weight+ bottom up

+ less boilerplate+ testing focus

Page 119: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Toothpick:-not idiot proof- performance

Page 120: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

Choose the right tool for your problem!

A Be

tter T

ool b

y Th

e M

arm

ot, C

C by

2.0

, flic

kr.c

om/p

hoto

s/th

emar

mot

/628

3203

163

Page 121: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

github.com/dpreussler/

understand_dependencies

Page 122: Demystifying dependency Injection: Dagger and Toothpick

@PreusslerBerlin

TP written byStephane Nicolas

Daniel Molinero Reguera

Presented byDanny Preussler

Special thanks toFlorina Muntenescu

Thank you!

VIACOM InternationalWe are hiring