Daggerを使ってSingletonにする仕組み
ものすごいあほうなことを書いているかもしれませんが、そのときはご指摘ください。
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よく分からん状態だったのですが、これで一歩前進できます。