このチュートリアル に従って、Dagger 2をAndroidプロジェクトに追加します。
セットアップを行い、モジュールとコンポーネントを作成した後、次のようなアクティビティに依存関係を追加できます。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account);
ButterKnife.bind(this);
((AppController) getApplication()).getNetComponent().inject(this);
}
FragmentとIntentServiceに依存関係を注入する方法に苦労していますか?
public class FragmentBrandList extends ListFragment {
}
このクラスでは、@Override
メソッドでインジェクションをリクエストする必要がありますが、このコードは何になりますか?
このクラスでは、どの@Overrideメソッドを使用する必要があり、フラグメントに依存関係を追加するコードは何ですか?
フラグメント内でインジェクションを呼び出す正しい場所は、onAttach(Context context)
です。これは、Dagger 2ユーザーガイドのwhere to injectセクションに記載されています here
_@Override
public void onAttach(Context context) {
((AppController) context.getApplicationContext()).getNetComponent().inject(this);
super.onAttach(context);
}
_
サービス内でインジェクションを呼び出す正しい場所はonCreate()
です
_@Override
public void onCreate() {
((AppController) getApplication()).getNetComponent().inject(this);
super.onCreate();
}
_
どちらの場合も、super.onCreate()
の呼び出しの前に注入の要求が来ることに注意してください。 Daggerユーザーガイドでは、次のように説明しています。
アクティビティのsuper.onCreate()の前にAndroidInjection.inject()を呼び出すことが重要です。これは、構成の変更中に前のアクティビティインスタンスからフラグメントをスーパーにアタッチし、フラグメントをインジェクトするためです。 Fragmentインジェクションが成功するためには、アクティビティがすでにインジェクトされている必要があります。 ErrorProneのユーザーにとって、super.onCreate()の後にAndroidInjection.inject()を呼び出すのはコンパイラエラーです。
言い換えると:
super.onCreate()
呼び出しは、前のインスタンスからフラグメントを再アタッチしますsuper
呼び出しにより、フラグメントが再注入されます(フラグメントはonAttach
に注入されるため)super.onCreate()
を呼び出す前にアクティビティに注入を要求してください。DaggerFragment
やDaggerService
などの_com.google.dagger:dagger-Android
_クラスに関連するソースコードを調べることで、いつどこに挿入するかを確認できます。 GitHubリポジトリはこちら を参照してください
具体的な例として、新しい注入サイトをNetComponentに追加したことを確認してください。
_void inject(FragmentBrandList frag);
void inject(BrandListService service);
_
ステップ1:ApplicationModuleを作成する
@Module
public class ApplicationModule {
private final DIApplication application;
public ApplicationModule(DIApplication application) {
this.application = application;
}
@Provides @Singleton
public DIApplication provideApplication() {
return application;
}
@Provides @Singleton
public DogModel provideDogModel() {
return new DogModelImpl("Scooby-doo");
}
}
ステップ2:ApplicationComponentを作成します。
@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
void inject(DIApplication application);
void inject(BaseActivity activity);
void inject(BaseFragment fragment);
void inject(DogSyncService service);
}
ステップ3:DIクラスを作成します。
public class DependencyInjector {
private static ApplicationComponent applicationComponent;
public static void initialize(DIApplication diApplication) {
applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(diApplication))
.build();
}
public static ApplicationComponent applicationComponent() {
return applicationComponent;
}
private DependencyInjector(){}
}
最終ステップ:次を使用してどこにでも注入:
DependencyInjector.applicationComponent()
あなたの質問から、Dagger2を使用してアクティビティ、フラグメント、およびサービスインジェクションを示すデモプロジェクトを作成することになりました。 gitは次のとおりです。 https://github.com/write2sv/AndroidDIDagger2/tree/master/app/src/main/Java/work/shaggy/didemo
_((AppController) getActivity().getApplication()).getNetComponent().inject(this);
_を使用してやった
Fragment.onCreate()
メソッド内。
_((MyApp) context.getApplicationContext()).getApplicationComponent().inject(MyFragment.this);
_
これをフラグメントのonAttach(Context context)
メソッドに追加しました。
autodagger2を使用すると、その定型文をすべて記述する必要がなくなります。私はこのアーキテクチャを頻繁に使用します。
build.gradle
apt 'com.github.lukaspili.autodagger2:autodagger2-compiler:1.1'
compile 'com.github.lukaspili.autodagger2:autodagger2:1.1'
YourApp.Java
@AutoComponent( modules = YourApp.YourAppModule.class )
public class YourApp extends Application {
private static YourApp instance;
private YourAppComponent component;
public YourAppComponent getComponent() {
return this.component;
}
@Override
public void onCreate() {
super.onCreate();
setupComponent();
}
private void setupComponent() {
component = DaggerYourAppComponent.builder()
.yourAppModule(new YourAppModule(instance))
.build();
}
@dagger.Module
public static class YourAppModule {
private YourApp app;
YourAppModule(YourAppApp application) {
this.app = application;
}
@Provides @AutoExpose(YourApp.class)
Application provideApplication() {
return app;
}
@Provides @AutoExpose(PoswalaApp.class)
Context provideContext() {
return app;
}
@Provides @AutoExpose(YourApp.class)
Retrofit provideApiAdapter() {
return ApiService.getServiceInstance();
}
}
}
YourActivity.Java
@AutoComponent(
dependencies = YourApp.class,
modules = YourActivity.YourActivityModule.class
)
public class YourActivity extends BaseActivity implements YourActivityView {
private YourActivityComponent component;
@Inject MyPresenter presenter
// This is an abstract method from BaseActivity
@Override
protected void setupComponent(YourAppComponent appComponent) {
component = DaggerYourActivityComponent.builder()
.yourAppComponent(((YourApp) getApplication()).getComponent())
.yourActivityModule(new YourctivityModule(this))
.build();
}
@Override
protected MyPresenter getPresenter() {
return presenter;
}
@dagger.Module
public static class YourActivityModule {
private YourActivityView view;
YourActivityModule(YourActivityView view) {
this.view = view;
}
@Provides @AutoExpose(YourActivity.class)
YourActivityView provideView() {
return view;
}
// Your other dependencies
}
}
簡単な説明:
アプリのモジュールは「ユニバーサル」な依存関係を持つ必要がありますが、この方法では、クラスに複数のモジュールを使用して達成できます。あなただけをカスタマイズする必要があります
@AutoComponent(
dependencies = YourApp.class,
modules = { YourActivity.YourActivityModule.class, YourFragment.YourFragmentModule.class }
)
ブロック。その構文を使用して、好きなだけモジュールを追加できます。
これがあなたを助けることを願っています
あなたは本当にあなたが注入したいもののためにインジェクタメソッドを含める必要があります。
@Singleton
@Component
public interface AppComponent {
void inject(MainActivity activity);
void inject(FragmentBrandList fragmentBrandList);
}