web-dev-qa-db-ja.com

ダガー@Reusableスコープと@Singleton

ユーザーズガイド から:

@Injectで構築されたクラスがインスタンス化される回数や@Providesメソッドが呼び出される回数を制限したい場合がありますが、特定のコンポーネントまたはサブコンポーネントのライフタイム中にまったく同じインスタンスが使用されることを保証する必要はありません。

@Singletonの代わりに使用するのはなぜですか?

36
philo

シングルトンの動作と保証に依存する場合は、@ Singletonを使用します。パフォーマンス上の理由でオブジェクトが@Singletonのみである場合は、@ Reusableを使用します。


@Reusableバインディングは、@ Singletonバインディングよりもスコープのないバインディングとの共通点がはるかに多くあります。新しいオブジェクトを作成しても問題ないことをDaggerに伝えていますが、便利なオブジェクトが既に作成されている場合はDagger mayそれを使用します。対照的に、@ Singletonオブジェクトguaranteeあなたはalwaysを受け取ります-sameインスタンスを受け取ります。

一般に、DaggerとDIはスコープ外のオブジェクトを好みます。新しいオブジェクトの作成は、状態をしっかりと保持する優れた方法であり、依存オブジェクトができるとすぐにオブジェクトをガベージコレクションできるようにします。 Daggerには、この設定の一部が組み込まれています。Daggerでは、コンポーネントにスコープ注釈が付けられているかどうかに関係なく、スコープのないオブジェクトを任意のコンポーネントまたはモジュールに混在させることができます。このタイプのスコープなしバインディングは、インジェクト可能な(モック可能な)ユーティリティクラスや strategycommand 、およびその他のポリモーフィック behavioralデザインパターン :オブジェクトはグローバルにバインドされ、テスト/オーバーライドのために挿入される必要がありますが、インスタンスは状態を保持せず、短命または使い捨てです。

ただし、Androidおよびその他のパフォーマンスとメモリに制約のある環境では、 多数の一時オブジェクトを作成することはパフォーマンスの推奨に反します 。インスタンスの作成とガベージコレクションは両方ともデスクトップVMよりも高価なプロセス:これは、常に同じインスタンスを取得することが重要であるためではなく、インスタンスを保存するためだけに、オブジェクトを@Singletonにマークする実用的なソリューションにつながります。メモリと速度への影響:短命のutilまたは戦略パターンオブジェクトは現在アプリケーションが存在する限り存在しなければなりませんであり、ダブルチェックロックを介してアクセスする必要があります。そうしないと、 「1つのインスタンスのみ」@Singletonの保証(ここでは不要)。これは、メモリ使用量と同期オーバーヘッドの増加の原因になる可能性があります。

妥協点は@Reusableバインディングにあります。@ Reusableバインディングは、@ Singletonのようなインスタンスを保存するプロパティを持ちますが、スコープのないバインディングと同様に scope-matching @Componentルールを除く です。 ( tests を参照してください。)ライフスパンは、それらを直接使用する最も外側のコンポーネントだけであり、さらに節約するために祖先のインスタンスを日和見的に使用しますが、 ダブルチェックロックなし 作成コストを節約します。最後に、そして最も重要なこととして、これらは、クラスの使用方法に関するあなたと将来の開発者へのシグナルです。

要するに、@ Singletonは機能しますが、@ Reusableには、オブジェクトのライフサイクルではなくパフォーマンスがポイントである場合、いくつかの明確なパフォーマンス上の利点があります。


saiedmomenからのフォローアップ質問「okhttpclient、retrofit、gsonのような100%明確なことは@Reusableと宣言する必要があります。 。 正しい??"

はい、一般的にステートレスユーティリティとライブラリ@Reusableとして宣言するのが良いと思います。ただし、接続制限の処理やすべてのコンシューマーでのバッチ処理などの状態を密かに保持している場合は、@Singletonにしたい場合があります。また、長期間有効なコンポーネントから非常にまれに使用する場合 =それらをガーベジコレクションできるようにスコープレスにすることは依然として理にかなっているかもしれません。ここですべてのケースとライブラリで機能する一般的なステートメントを作成するのは非常に困難です。ライブラリの機能、メモリの重み、インスタンス化コスト、および関連するオブジェクトの予想寿命に基づいて決定する必要があります。

特にOkHttpClientは、 Wyko がコメントで指摘しているように、 インスタンスごとに独自の接続とスレッドプールを管理します を実行します。 @Singletonよりも@Reusableの良い候補になるでしょう。ありがとう、Wyko!

73
Jeff Bowman