Je suis ce tutoriel pour ajouter Dagger 2 à mon projet Android.
Après avoir configuré et créé les modules et les composants, je peux ajouter les dépendances dans une activité comme celle-ci:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account);
ButterKnife.bind(this);
((AppController) getApplication()).getNetComponent().inject(this);
}
J'ai du mal à injecter des dépendances dans Fragment and IntentService?
public class FragmentBrandList extends ListFragment {
}
Dans cette classe, quelle méthode @Override
dois-je demander l'injection et quel sera le code pour cela?
Dans cette classe, quelle méthode @Override je devrais utiliser et quel sera le code pour ajouter la dépendance dans fragment?
Le bon endroit pour appeler l'injection à l'intérieur d'un fragment est onAttach(Context context)
. Ceci est indiqué dans la section où injecter du guide de l'utilisateur Dagger 2 ici
@Override
public void onAttach(Context context) {
((AppController) context.getApplicationContext()).getNetComponent().inject(this);
super.onAttach(context);
}
Le bon endroit pour appeler une injection dans un service est onCreate()
@Override
public void onCreate() {
((AppController) getApplication()).getNetComponent().inject(this);
super.onCreate();
}
Notez que dans les deux cas, la demande d’injection intervient avant l’appel de super.onCreate()
. Le manuel d'utilisation de la dague l'explique comme suit:
Il est essentiel d'appeler AndroidInjection.inject () avant super.onCreate () dans une activité, car l'appel à super attache des fragments de l'instance d'activité précédente lors du changement de configuration, qui injecte à son tour les fragments. Pour que l'injection de fragment réussisse, il faut que l'activité soit déjà injectée. Pour les utilisateurs de ErrorProne, le fait d'appeler AndroidInjection.inject () après super.onCreate () est une erreur du compilateur.
En d'autres termes:
super.onCreate()
rattache des fragments d’une instance précédente super
provoque la réinjection de fragments (puisque les fragments sont injectés dans onAttach
)super.onCreate()
.Vous pouvez toujours vérifier où injecter en consultant le code source correspondant aux classes com.google.dagger:dagger-Android
telles que DaggerFragment
et DaggerService
. Voir le dépôt GitHub ici
Pour votre exemple spécifique, assurez-vous d’avoir ajouté les nouveaux sites d’injection au NetComponent:
void inject(FragmentBrandList frag);
void inject(BrandListService service);
Étape 1: Créez votre 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");
}
}
Étape 2: Créez votre composant d'application:
@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
void inject(DIApplication application);
void inject(BaseActivity activity);
void inject(BaseFragment fragment);
void inject(DogSyncService service);
}
Étape 3: Créer une classe d’ID:
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(){}
}
Dernière étape: Injectez n’importe où en utilisant:
DependencyInjector.applicationComponent()
Votre question m'a inspiré pour créer un projet de démonstration montrant l'injection d'activité, de fragment et de service à l'aide de Dagger2. Voici le git: https://github.com/write2sv/AndroidDIDagger2/tree/master/app/src/main/Java/work/shaggy/didemo
Je l'ai fait en utilisant ((AppController) getActivity().getApplication()).getNetComponent().inject(this);
dans la méthode Fragment.onCreate()
.
((MyApp) context.getApplicationContext()).getApplicationComponent().inject(MyFragment.this);
J'ai ajouté ceci dans la méthode onAttach(Context context)
du fragment.
Vous pouvez utiliser Autadogger pour éviter d'avoir à écrire tout ce passe-partout. J'utilise cette architecture assez souvent:
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
}
}
Explication rapide:
Le module de votre application devra avoir une dépendance "universelle", mais vous pourrez ainsi utiliser plusieurs modules pour une classe. Vous avez juste besoin de personnaliser le
@AutoComponent(
dependencies = YourApp.class,
modules = { YourActivity.YourActivityModule.class, YourFragment.YourFragmentModule.class }
)
bloc. Vous pouvez ajouter autant de modules que vous le souhaitez en utilisant cette syntaxe.
J'espère que cela vous aide
Vous avez vraiment besoin d'inclure la méthode d'injection pour ce que vous voulez injecter.
@Singleton
@Component
public interface AppComponent {
void inject(MainActivity activity);
void inject(FragmentBrandList fragmentBrandList);
}