_Dagger2
_を使用してアプリを改善し、コードを保守しやすくしようとしていますが、一般的なアイデアは捉えましたが、スコープが_Dagger2
_によってどのように管理されているのかまだわかりません(プロジェクトに短剣を注入しました)。 ApplicationComonent
コンポーネントを作成しましたが、私のプロジェクトでは完全に機能します。これが私のコードです。
_@Singleton
@Component(modules = {
ApplicationModule.class,
ThreadingModule.class,
NetworkModule.class,
DatabaseModule.class,
ServiceModule.class,
ParseModule.class,
PreferencesSessionModule.class})
public interface ApplicationComponent {
ActivityComponent activityComponent(ActivityModule activityModule);
void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
void inject(MyApplication application);
void inject(BaseFragment baseFragment);
void inject(MyService service);
void inject(RegistrationIntentService service);
}
_
次のようにMyApplication
クラスにコンポーネントインスタンスを作成します
_private void initializeAndInjectComponent() {
mApplicationComponent =
DaggerApplicationComponent
.builder()
.threadingModule(new ThreadingModule(1))
.applicationModule(new ApplicationModule(this))
.networkModule(new NetworkModule(
MyService.API_SERVER_BASE_URL,
MyService.TIMEOUT))
.build();
mApplicationComponent.inject(this);
}
_
そして、Activities
に注入するためのコンポーネントを取得できます
_ MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
_
すべてが完璧に動作します。
各メソッドとモジュールクラスを追加するには、_@Singleton
_スコープで注釈を付けます。ApplicationComponent
に関連するすべてのモジュール
依存関係を改善したいので、_@PerActivity
_、_@PerFragment
_などのカスタムスコープを持つ多くの例を見てきました。多くの質問がありますが、これについては後で説明します。
だから私はActivityComponent
を作成しました
_@PerActivity
@Subcomponent(
modules = {
NetworkServiceModule.class,
ActivityModule.class,
PermissionModule.class
})
public interface ActivityComponent {
Activity activity();
void inject(BaseActivity baseActivity);
}
_
すべてのモジュールはこのようになります
_@PerActivity
@Module
public class ActivityModule {
private Activity mActivity;
public ActivityModule(Activity activity) {
this.mActivity = activity;
}
@Provides
@PerActivity
Activity provideActivity() {
return this.mActivity;
}
}
_
BaseActivity
に次の依存関係があります
_// Dependencies from ApplicationComponent
@Inject
protected ApplicationSettingsManager mApplicationSettingsManager;
@Inject
protected ScheduledThreadPoolExecutor mPoolExecutor;
// Dependencies from ActivityComponent
@Inject
protected SpiceManager mSpiceManager;
@Inject
protected PermissionController mPermissionController;
_
そして、私のonCreate()
メソッドでは、次のように注入しています
_ MyApplication application = MyApplication.get(this);
application.getApplicationComponent().activityComponent(new ActivityModule(this)).inject(this);
_
サブコンポーネントActivityComponent
を作成する前は
_ MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
_
エラーが発生しました
_Error:(34, 10) error: com.octo.Android.robospice.SpiceManager cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
BaseActivity.mSpiceManager
[injected field of type: com.octo.Android.robospice.SpiceManager mSpiceManager]
_
どこに問題があるのか、見逃してしまったのかわかりません。 dagger2のスコープに関する私の質問。
_@Singleton
_以外はDagger 2で無視されますか?コンポーネントの寿命がどのように管理されているのかわかりません。私はたった一つのアイデアを持っています
_@Singleton
_アノテーションを使用すると、短剣はアプリケーションのライフサイクル全体で存在する静的プールにオブジェクトを作成し、JVMプロセス(dalvik VM、ART)インスタンスが破棄されると破棄されます。
他の注釈を使用する場合は、開発者がコードを適切に維持するためだけに必要です。_@PerActivity
_、_@PerFragment
_は、単なるカスタム注釈です。また、_@PerFragment
_コンポーネントをアプリケーションクラスに配置した場合、アプリケーションが存続する限り存続します。私は正しいですか?
だから私はこれをこのように理解し、daggerが_@Singleton
_アノテーションを見つけると、コンポーネントが最初に作成されたときにコンポーネントへの静的参照を追加し、他のアノテーションの場合はコンポーネントへの参照を保持しません。
上記の問題の助けに感謝します。
[〜#〜]更新[〜#〜]
_David Medenjak
_の回答ありがとうございます。_Dagger2
_についてよく理解できました。
私は問題を見つけたばかりですが、今は別のActivity
コンポーネントを使用している限り、ApplicationComponent
の2行を忘れて、MainActivity
のinejctionをActivityComponent
ではなくApplicationComponent
に変更して、サブコンポーネントからの依存関係を解決できないことを確認しました。
_ void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
_
これですべてが完璧に動作し、_Dagger2
_と分離アーキテクチャが好きです。
少し過激ですが、物事を単純化するために:すべてのScopeアノテーションは、@Singleton
。を含め、構文上の砂糖にすぎません。
スコープは主にコンパイル時のチェックを提供するだけです。循環依存関係、または見逃した可能性のあるものに関するエラー。 @Singleton
は他のスコープと同じですが、唯一の違いは、既存のアノテーションであり、自分で作成する必要がないことです。代わりに@MySingleton
を使用できます。
[...] daggerは、アプリケーションのライフサイクル全体で存在する静的プールにオブジェクトを作成しています
いいえ、ダガーは何もしません静的です。コンポーネントオブジェクトがあります。これらのコンポーネントは、モジュールによって作成されたオブジェクトを保持します。コンポーネント内のオブジェクトにコンポーネントのスコープがある場合、そのオブジェクトはその正確なコンポーネント内に1回だけ作成されます。 2つのAppComponent
オブジェクトを作成する場合、@Singleton
注釈付きオブジェクトごとに2つのオブジェクトがあり、それぞれがコンポーネント内にあります。これがあなたがすべき理由ですコンポーネントへの参照を保持します。私が見たり使用したりしたほとんどの実装は、それらのAppComponent
をApplication
内に保持します。これを行うと、シングルトンのようにlikeを使用できます。これはまだ単なるPOJOです。
[...] @PerFragmentコンポーネントをApplicationクラスに配置すると、Applicationが存続する限り存続します。
はい。上記の段落ですでに説明したように、これは単なるオブジェクトです。参照を維持し、オブジェクトを維持します。それを捨てるか、新しいオブジェクトを作成し、新しいオブジェクト(このコンポーネント/スコープ内で定義されている)を取得します。ただし、しないでくださいアクティビティまたはフラグメントスコープコンポーネントは、アクティビティまたはフラグメント以外の場所にそれぞれ保持する必要があります。アプリコンポーネントでメモリリークが発生する可能性があります。 (そうでない場合は、おそらくアクティビティまたはフラグメントのスコープは必要なかったでしょう。)
daggerが
@Singleton
アノテーションを見つけると、コンポーネントが最初に作成されたときにコンポーネントへの静的参照を追加し、他のアノテーションの場合はコンポーネントへの参照を保持しません。
繰り返しますが、違います。静的なものはありません。単純な古いJavaオブジェクト。独自のオブジェクトを使用して複数の@Singleton
コンポーネントを持つことができますが、おそらくそうすべきではありません(これにより、インスツルメンテーションテストが可能/簡単になりますが、コンポーネントを交換するだけです) 。)
SpiceManagerは、@ Injectコンストラクターなしで、または@ Provides-または@ Produces-annotatedメソッドから提供できません。
つまり、オブジェクトを挿入しようとしているコンポーネントは、SpiceManager
を生成または提供する方法を見つけることができません。 AppComponentまたは他の場所から提供していること、アノテーションなどがないことを確認してください。