ほげほげ(仮)

仮死状態

Dagger2メモ

Dagger2で最近知ったことのメモです。

バージョンは2.11-rc2

Component.Builder

Moduleが必要とするパラメータを渡して、Moduleのインスタンス化をDagger側でやってもらう。

AppComponent内に@Component.Builderをつけたinterfaceを作って、そこに使用してるModuleのパラメータを@BindsInstanceで指定してあげる。

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

    @Component.Builder
    interface Builder {
        // Moduleが必要とするパラメータ
        @BindsInstance
        Builder application(Application application);

        // コレないとビルドエラーになる
        AppComponent build();
    }

    void inject(MainActivity activity);
}
@Module
public class AppModule {

    @Singleton
    @Provides
    HogeRepository provideHogeRepository(Application application) {
        return new HogeRepositoryImpl(application);
    }
}

AppComponentを取得するときに、new AppModuleをしなくてよくなり、そのかわり指定したパラメータを渡すようにする。

public class App extends Application {

    private AppComponent appComponent;

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

        appComponent = DaggerAppComponent
                .builder()
                .application(this)  // AppComponentのBuilderに設定したメソッド
                .build();
    }

    public AppComponent getAppComponent() {
        return appComponent;
    }
}

Dagger2のAndroid拡張

なんか使い方が色々あってわからないこと多い。

とりあえず、一番シンプルな使い方。AndroidInjection.inject(this)が動くようにする。

まずはGradle。新しくAndroid拡張のものを追加します。

compile 'com.google.dagger:dagger:2.11-rc2'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11-rc2'
compile 'com.google.dagger:dagger-android:2.11-rc2'
compile 'com.google.dagger:dagger-android-support:2.11-rc2'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.11-rc2'

次にinjectをするActivityのModule作成。@ContributesAndroidInjectorというアノテーションをつけてinjectを行うActivityを指定する感じ。

@Module
public abstract class ActivityBuilderModule {

    @ContributesAndroidInjector
    abstract MainActivity contributeMainActivity();
}

AppComponentは新たに2つのModuleの指定を追加してます。AndroidSupportInjectionModuleAndroid拡張を使うために必要っぽい(よく分かってない)。いらないっぽい(よく分かってない)。もう一つは、先程のActivityBuilderModuleも追加してます。AppModuleはBuilderのとこで書いたものと同じです。

あとApplicationクラスを受け取るinjectメソッドを追加します。

@Singleton
@Component(modules = {AndroidSupportInjectionModule.class, AppModule.class, ActivityBuilderModule.class})
public interface AppComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);

        AppComponent build();
    }

    void inject(App app);
}

ApplicationクラスではHasActivityInjectorというinterfaceを実装して、DispatchingAndroidInjectorを返すメソッドを追加します。

で、そのDispatchingAndroidInjector自体の生成はDaggerに任せちゃう感じ、Applicationクラスでinjectします。

public class App extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

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

        DaggerAppComponent
                .builder()
                .application(this)
                .build()
                .inject(this);
    }

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}

Activity側はAndroidInjection.inject(this)を呼ぶだけです。 ドキュメントにはsuper.onCreate()の前に呼ぶようにと書いてます。試しにその後に書いても動いたのでよくわからない…

public class MainActivity extends AppCompatActivity {

    @Inject
    HogeRepository repository;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

まとめ

雰囲気でDagger2を使ってる