読むと怖くないdagger2
TRANSCRIPT
読むと怖くないDagger2
kyobashi.dex #1
プロフィール
釘宮 愼之介 / @kgmyshin
Androidエンジニア
福岡県福岡市南区野多目出身
この資料の目的
Dagger2で生成されるソースを読んで、
動きを理解する
今回話さないこと•DIとは
•Dagger2の使い所
•どういう構成にするか
•DaggerとDagger2の違い
今回話すこと
ひたすら生成されたソースを見て
裏でどういう動きをするのかを見る
Target Annotation•Component
•Module
•Singleton
•Inject
•Scope
Target Annotation•Component
•Module
•Singleton
•Inject
•Scope 時間的に無理でした
Case 1 Minimum
public interface Bread {}
public class Chokokorone implements Bread {}
@Component(modules = BreadModule.class) interface BreadShop { Bread bread(); }
@Modulepublic class BreadModule { @Provides Bread provideBread() { return new Chokokorone(); } }
BreadShop shop = DaggerBreadShop .builder() .breadModule(new BreadModule()) .build();
Bread bread = shop.bread();
BreadShop shop = DaggerBreadShop .builder() .breadModule(new BreadModule()) .build();
Bread bread = shop.bread(); // Chokokorone
Generated Codes• DaggerBreadShop
• BreadModule_ProvideBreadFactory
@Generated("dagger.internal.codegen.ComponentProcessor") public final class DaggerBreadShop implements BreadShop { private Provider<Bread> provideBreadProvider; private DaggerBreadShop(Builder builder) { assert builder != null; initialize(builder); } public static Builder builder() { return new Builder(); } public static BreadShop create() { return builder().build(); } private void initialize(final Builder builder) { this.provideBreadProvider = BreadModule_ProvideBreadFactory.create(builder.breadModule); } @Override public Bread bread() { return provideBreadProvider.get(); } public static final class Builder { private BreadModule breadModule; private Builder() { } public BreadShop build() { if (breadModule == null) { this.breadModule = new BreadModule(); } return new DaggerBreadShop(this); } public Builder breadModule(BreadModule breadModule) { if (breadModule == null) { throw new NullPointerException("breadModule"); } this.breadModule = breadModule; return this; } }}
return provideBreadProvider.get(); } public static final class Builder { private BreadModule breadModule; private Builder() { } public BreadShop build() { if (breadModule == null) { this.breadModule = new BreadModule(); } return new DaggerBreadShop(this); } public Builder breadModule(BreadModule breadModule) { if (breadModule == null) { throw new NullPointerException("breadModule"); } this.breadModule = breadModule; return this; } }}
return provideBreadProvider.get(); } public static final class Builder { private BreadModule breadModule; private Builder() { } public BreadShop build() { if (breadModule == null) { this.breadModule = new BreadModule(); } return new DaggerBreadShop(this); } public Builder breadModule(BreadModule breadModule) { if (breadModule == null) { throw new NullPointerException("breadModule"); } this.breadModule = breadModule; return this; } }}
@Generated("dagger.internal.codegen.ComponentProcessor") public final class DaggerBreadShop implements BreadShop { private Provider<Bread> provideBreadProvider; private DaggerBreadShop(Builder builder) { assert builder != null; initialize(builder); } private void initialize(final Builder builder) { this.provideBreadProvider = BreadModule_ProvideBreadFactory.create(builder.breadModule); } @Override public Bread bread() { return provideBreadProvider.get(); } public static final class Builder { private BreadModule breadModule; private Builder() { }
@Generated("dagger.internal.codegen.ComponentProcessor")public final class DaggerBreadShop implements BreadShop { private Provider<Bread> provideBreadProvider; private DaggerBreadShop(Builder builder) { assert builder != null; initialize(builder); } private void initialize(final Builder builder) { this.provideBreadProvider = BreadModule_ProvideBreadFactory.create(builder.breadModule); } @Override public Bread bread() { return provideBreadProvider.get(); } public static final class Builder { private BreadModule breadModule; private Builder() { }
@Generated("dagger.internal.codegen.ComponentProcessor") public final class BreadModule_ProvideBreadFactory implements Factory<Bread> { private final BreadModule module; public BreadModule_ProvideBreadFactory(BreadModule module) { assert module != null; this.module = module; } @Override public Bread get() { Bread provided = module.provideBread(); if (provided == null) { throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method"); } return provided; } public static Factory<Bread> create(BreadModule module) { return new BreadModule_ProvideBreadFactory(module); } }
@Generated("dagger.internal.codegen.ComponentProcessor")public final class BreadModule_ProvideBreadFactory implements Factory<Bread> { private final BreadModule module; public BreadModule_ProvideBreadFactory(BreadModule module) { assert module != null; this.module = module; } @Override public Bread get() { Bread provided = module.provideBread(); if (provided == null) { throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method"); } return provided; } public static Factory<Bread> create(BreadModule module) { return new BreadModule_ProvideBreadFactory(module); }}
DaggerBreadShop::bread()
DaggerBreadShop::bread()
BreadModule_ProvideBreadFactory::get()
DaggerBreadShop::bread()
BreadModule_ProvideBreadFactory::get()
BreadModule::provideBread()
DaggerBreadShop::bread()
BreadModule_ProvideBreadFactory::get()
BreadModule::provideBread()
new Chokokorone()!!
Case 2 Singleton
@Component(modules = BreadModule.class) interface BreadShop { Bread bread(); }
@Modulepublic class BreadModule { @Provides Bread provideBread() { return new Chokokorone(); } }
Before
@Singleton @Component(modules = BreadModule.class) interface BreadShop { Bread bread(); }
@Modulepublic class BreadModule { @Singleton @Provides Bread provideBread() { return new Chokokorone(); } }
After
@Singleton @Component(modules = BreadModule.class)interface BreadShop { Bread bread();}
@Modulepublic class BreadModule { @Singleton @Provides Bread provideBread() { return new Chokokorone(); }}
After
Generated Codes• DaggerBreadShop
• BreadModule_ProvideBreadFactory
Generated Codes• DaggerBreadShop
• BreadModule_ProvideBreadFactory
private void initialize(final Builder builder) { this.provideBreadProvider = BreadModule_ProvideBreadFactory.create(builder.breadModule); }
Before
private void initialize(final Builder builder) { this.provideBreadProvider = ScopedProvider.create( BreadModule_ProvideBreadFactory.create(builder.breadModule) ); }
After
private void initialize(final Builder builder) { this.provideBreadProvider = ScopedProvider.create( BreadModule_ProvideBreadFactory.create(builder.breadModule) ); }
After
public final class ScopedProvider<T> implements Provider<T> { : @Override public T get() { // double-check idiom from EJ2: Item 71 Object result = instance; if (result == UNINITIALIZED) { synchronized (this) { result = instance; if (result == UNINITIALIZED) { instance = result = factory.get(); } } } return (T) result; } : }
DaggerBreadShop::bread()
DaggerBreadShop::bread()
ScopedProvider::get()
DaggerBreadShop::bread()
ScopedProvider::get()
BreadModule::provideBread()
DaggerBreadShop::bread()
ScopedProvider::get()
BreadModule::provideBread()
new Chokokorone()!! (1度取得したら使い回す)
Case 3 Inject
@Component(modules = BreadModule.class) interface BreadShop { Bread bread(); }
Before
BreadShop shop = DaggerBreadShop .builder() .breadModule(new BreadModule()) .build();
Bread bread = shop.bread();
Before
@Component(modules = BreadModule.class) interface BreadShop { void bread(Lunch lunch); }
After
public class Lunch { @Inject Bread bread; }
@Component(modules = BreadModule.class)interface BreadShop { void bread(Lunch lunch); }
After
public class Lunch { @Inject Bread bread; }
BreadShop shop = DaggerBreadShop .builder() .breadModule(new BreadModule()) .build(); Lunch lunch = new Lunch(); shop.bread(lunch); // lunch.bread is Chokokorone
After
BreadShop shop = DaggerBreadShop .builder() .breadModule(new BreadModule()) .build();Lunch lunch = new Lunch(); shop.bread(lunch); // lunch.bread is Chokokorone
After
Generated Codes• DaggerBreadShop
• BreadModule_ProvideBreadFactory
• Lunch_MembersInjector
Generated Codes• DaggerBreadShop
• BreadModule_ProvideBreadFactory
• Lunch_MembersInjector
private void initialize(final Builder builder) { this.provideBreadProvider = BreadModule_ProvideBreadFactory.create(builder.breadModule); } @Override public Bread bread() { return provideBreadProvider.get(); }
Before
private void initialize(final Builder builder) { this.provideBreadProvider = BreadModule_ProvideBreadFactory.create(builder.breadModule); this.lunchMembersInjector = Lunch_MembersInjector.create(provideBreadProvider); } @Override public void bread(Lunch lunch) { lunchMembersInjector.injectMembers(lunch); }
After
private void initialize(final Builder builder) { this.provideBreadProvider = BreadModule_ProvideBreadFactory.create(builder.breadModule); this.lunchMembersInjector = Lunch_MembersInjector.create(provideBreadProvider); } @Override public void bread(Lunch lunch) { lunchMembersInjector.injectMembers(lunch); }
After
@Generated("dagger.internal.codegen.ComponentProcessor") public final class Lunch_MembersInjector implements MembersInjector<Lunch> { private final Provider<Bread> breadProvider; public Lunch_MembersInjector(Provider<Bread> breadProvider) { assert breadProvider != null; this.breadProvider = breadProvider; } @Override public void injectMembers(Lunch instance) { if (instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } instance.bread = breadProvider.get(); } public static MembersInjector<Lunch> create(Provider<Bread> breadProvider) { return new Lunch_MembersInjector(breadProvider); } }
@Generated("dagger.internal.codegen.ComponentProcessor")public final class Lunch_MembersInjector implements MembersInjector<Lunch> { private final Provider<Bread> breadProvider; public Lunch_MembersInjector(Provider<Bread> breadProvider) { assert breadProvider != null; this.breadProvider = breadProvider; } @Override public void injectMembers(Lunch instance) { if (instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } instance.bread = breadProvider.get(); } public static MembersInjector<Lunch> create(Provider<Bread> breadProvider) { return new Lunch_MembersInjector(breadProvider); }}
DaggerBreadShop::bread(Lunch launch)
DaggerBreadShop::bread(Lunch launch)
Lunch_MembersInjector::injectMembers(Lunch launch)
DaggerBreadShop::bread(Lunch launch)
Lunch_MembersInjector::injectMembers(Lunch launch)
lunch = BreadModule_ProvideBreadFactory::get()
DaggerBreadShop::bread(Lunch launch)
Lunch_MembersInjector::injectMembers(Lunch launch)
lunch = BreadModule_ProvideBreadFactory::get()
lunch = BreadModule::provideBread()
DaggerBreadShop::bread(Lunch launch)
Lunch_MembersInjector::injectMembers(Lunch launch)
lunch = BreadModule_ProvideBreadFactory::get()
lunch = BreadModule::provideBread()
lunch = new Chokokorone()!!
まとめ
Dagger2は怖くない