Daggerを使ってSingletonにする仕組み

この記事は最終更新から3ヶ月以上が経過しています。情報が古い可能性があります。

ものすごいあほうなことを書いているかもしれませんが、そのときはご指摘ください。

Daggerを使って依存性を注入する際に、アプリ内でSingletonになるようにすることあるじゃないですか。

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    void inject(MainActivity activity);
}

@Module
public class AppModule {
    private Context context;
    public AppModule(Context context) {
        this.context = context;
    }

    @Provides
    @Singleton
    public SomeClass provideSomeClass() {
        return new SomeClass().initializeWithDefault();
    }
}

みたいに、SomeClassがアプリ内でシングルトンになるようにすると。

今までずっと、@Singletonって指定してるから実現できてるんだと思っておりました。実際には違います。これはそもそもAppComponent自体がアプリ内でシングルトンになっていなければ実現されません。

このAppComponentはApplicationクラスを拡張して、そこで初期化してるから@Singletonという指定が効くのです。このAppComponentを、ActivityのonCreateで初期化していたらシングルトンにはなりません。AppComponentインスタンスの中ではSomeClassのインスタンスは一度生成されたら使いまわされますが、AppComponentのインスタンスが複数生まれてしまえば生成されるSomeClassもAppComponentのインスタンスの数と同じだけ増えていくことになります。

そして@Singletonは別に@Singletonでなくてもいいのです。自分でスコープを作って、例えば

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

@Module
public class AppModule {
    @Provides
    @AppScope
    public SomeClass provideSomeClass() {
    }
}

としても結果は同じです。Componentにつけたスコープ名の中でインスタンスを使いまわすっていう感じになるわけです。

だから@Singletonつけてるからシングルトンになるわけではないのです。AppComponentのインスタンスがアプリ内で1つだからこそ、シングルトンにできているわけです。

ここがあやふやなままだったので、Daggerよく分からん状態だったのですが、これで一歩前進できます。

ご意見ご感想はこちら

お名前 (必須)

メールアドレス (必須)

メッセージ本文

メッセージを送信するにはチェックを付けてください。