私はダガー2を使い始めました。このシナリオがあります。アプリ全体(プレゼンター、API)にオブジェクトを挿入する必要はありません。
最初は提供する方法がありません。私のアプリのある段階で認証が完了するまで作成されません。
ドキュメントから http://google.github.io/dagger/
私は遅延読み込みがこれを解決する方法かもしれないと思います
@Inject
Lazy<Grinder> lazyGrinder;
そして、次のようにして、このような値を取得します。lazyGrinder.get()。Grind();
私の質問は:
ありがとう
これはLazy
には適していません。 Lazy
は、負荷の高いオブジェクトの初期化を遅延させる優れた方法ですが、特に必要な「安全なスワップ」動作に関して、不要または不要なセマンティクスを意味します。
簡単に言うと、Lazyは memoize をローカルに提供するプロバイダーラッパーです。
get
を呼び出さない場合、Daggerは問題のオブジェクトを作成しません。get
への最初の呼び出しは、オブジェクトインスタンスを作成して保存します。get
への2回目の呼び出しでは、オブジェクトがシングルトンとしてマークされているかどうかに関係なく、同じインスタンスが返されます。これにより、Lazyは、フィールドである(ただし、使用されることはない)高価なオブジェクトの優れた選択肢となります。ただし、参照が(意図したとおりに)変更される可能性がある場合、Lazyは単純に混乱します。最初の使用時に値を格納し、ローカルで更新することはないため、複数の古いコピーがアプリケーション内で浮いている可能性がありますいつでも「正しい」値が何であるかについて。
あなたの例からグラインダーの使用を借りるために、より良い解決策は以下を含みます:
を使って @Provides
メソッドは、後で更新できるモジュールのフィールドを返します。注入する必要がありますProvider<Grinder>
長期間有効なオブジェクトインスタンスごと。これは、Grinderへの注入された参照だけでは更新されないためです。寿命の短いオブジェクトがたくさんある場合は、これが最善の策かもしれません。
参照は暗黙的にシングルトンですが、インスタンスを自分で制御しているため、注釈は付けられていません。 DaggerはgetGrinder
メソッドを頻繁に呼び出します。
@Module public class YourModule {
private Grinder grinder;
public void setGrinder(Grinder grinder) {
this.grinder = grinder;
}
@Provides public Grinder getGrinder() {
return grinder;
}
}
/* elsewhere */
YourModule module = new YourModule();
YourComponent component = DaggerYourComponent.builder()
.yourModule(module)
.build();
/* ... */
module.setGrinder(latestAndGreatestGrinder);
EpicPandaForceがコメントで述べたように、現在のインスタンスを提供し、更新を可能にするシングルトンGrinderHolder、GrinderController、またはAtomicReferenceオブジェクトを作成/バインドします。この方法では、Grinderを直接注入することは不可能ですが、現在の正しいGrinderをフェッチするオブジェクトを注入することは簡単で明白です。シングルトンGrinderHolder実装が最初に要求するまでGrinderを作成しない場合は、自分でLazyシングルトンを効果的に作成したことになります。
コンポーネントの作成時にオブジェクトを提供できない場合は、コンポーネントグラフに追加しないでください。それは、混乱するグラフの依存関係と矛盾を求めています。検討していることに対するより良い解決策は、@Subcomponent
アプローチです。これにより、親から依存関係を継承するだけでなく、新しいコンポーネントを追加する新しいコンポーネントを作成できます。次に例を示します。
@Component
interface RegularComponent {
@AppInstanceId String appInstanceId(); // unique per app install; not related to logging in
AuthenticatedComponent newAuthenticatedComponent();
}
@Subcomponent
interface AuthenticatedComponent {
Set<Friend> friends();
@AccountId String accountId();
}
ここで、サブコンポーネントはその親コンポーネントと依存関係を共有しているため、サブコンポーネントの@AccountId
はappInstanceId
を使用してアカウントID(必要な場合)を提供できます。
(accountId、authトークンなどを使用して)サブコンポーネントのモジュールに状態を提供する必要がある場合は、@Module
にパラメーターとして渡し、private final
フィールドに保存してください。サブコンポーネントモジュールを提供する方法の詳細については、 ドキュメント内 を参照してください。