Ich folge diesem Tutorial , um Dagger 2 meinem Android-Projekt hinzuzufügen.
Nach dem Einrichten und Erstellen der Module und Komponenten kann ich die Abhängigkeiten in einer Aktivität wie folgt hinzufügen:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account);
ButterKnife.bind(this);
((AppController) getApplication()).getNetComponent().inject(this);
}
Ich habe Probleme damit, wie man Abhängigkeiten in ein Fragment und einen IntentService einfügt.
public class FragmentBrandList extends ListFragment {
}
In welcher Klasse soll ich die @Override
-Methode anfordern und wie lautet der Code dafür?
In dieser Klasse, welche @Override-Methode ich verwenden soll, und was wird der Code sein, um die Abhängigkeit in Fragment hinzuzufügen?
Die korrekte Stelle zum Aufrufen der Injektion in einem Fragment ist onAttach(Context context)
. Dies ist im Abschnitt wo zu injizieren des Dagger 2-Benutzerhandbuchs hier angegeben.
@Override
public void onAttach(Context context) {
((AppController) context.getApplicationContext()).getNetComponent().inject(this);
super.onAttach(context);
}
Der richtige Ort, um die Injektion innerhalb eines Dienstes aufzurufen, ist onCreate()
@Override
public void onCreate() {
((AppController) getApplication()).getNetComponent().inject(this);
super.onCreate();
}
Beachten Sie, dass in beiden Fällen die Aufforderung zur Injektion vor dem Aufruf von super.onCreate()
erfolgt. Das Dagger-Benutzerhandbuch erklärt es so:
Es ist wichtig, AndroidInjection.inject () vor super.onCreate () in einer Activity aufzurufen, da der Aufruf von Super Fragmente aus der vorherigen Aktivitätsinstanz während der Konfigurationsänderung anfügt, wodurch die Fragmente eingefügt werden. Damit die Fragmentinjektion erfolgreich ist, muss die Aktivität bereits injiziert werden. Für Benutzer von ErrorProne ist es ein Compiler-Fehler, AndroidInjection.inject () nach super.onCreate () aufzurufen.
Mit anderen Worten:
super.onCreate()
-Aufruf werden Fragmente aus einer vorherigen Instanz erneut angefügt super
-Aufruf bewirkt, dass Fragmente erneut injiziert werden (da Fragmente in onAttach
injiziert werden).super.onCreate()
aufrufen.Sie können immer überprüfen, wo Sie injizieren sollen, indem Sie den entsprechenden Quellcode für die com.google.dagger:dagger-Android
-Klassen wie DaggerFragment
und DaggerService
betrachten. Siehe das GitHub-Repo hier
Stellen Sie für Ihr spezielles Beispiel sicher, dass Sie die neuen Injektionsstellen zur NetComponent hinzugefügt haben:
void inject(FragmentBrandList frag);
void inject(BrandListService service);
Schritt 1: Erstellen Sie Ihr 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");
}
}
Schritt 2: Erstellen Sie Ihre 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);
}
Schritt 3: Erstellen Sie eine DI-Klasse:
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(){}
}
Letzter Schritt: Injizieren Sie überall mit:
DependencyInjector.applicationComponent()
Ihre Frage hat mich dazu inspiriert, ein Demoprojekt zu erstellen, das Aktivität, Fragment und Service mit Dagger2 zeigt. Hier ist der Git: https://github.com/write2sv/AndroidDIDagger2/tree/master/app/src/main/Java/work/shaggy/didemo
Ich habe es gemacht mit ((AppController) getActivity().getApplication()).getNetComponent().inject(this);
in der Fragment.onCreate()
-Methode.
((MyApp) context.getApplicationContext()).getApplicationComponent().inject(MyFragment.this);
Ich habe dies in der onAttach(Context context)
-Methode des Fragments hinzugefügt.
Sie können den Autadogger verwenden, um zu vermeiden, dass die gesamte Boilerplate geschrieben werden muss. Ich verwende diese Architektur sehr oft:
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
}
}
Kurze Erklärung:
Das Modul Ihrer App muss eine "universelle" Abhängigkeit haben. Auf diese Weise können Sie jedoch mehrere Module für eine Klasse verwenden. Sie müssen nur das anpassen
@AutoComponent(
dependencies = YourApp.class,
modules = { YourActivity.YourActivityModule.class, YourFragment.YourFragmentModule.class }
)
block. Sie können mit dieser Syntax beliebig viele Module hinzufügen.
Hoffe das hilft dir
Sie müssen nur die Injektormethode für alles einschließen, was Sie injizieren möchten.
@Singleton
@Component
public interface AppComponent {
void inject(MainActivity activity);
void inject(FragmentBrandList fragmentBrandList);
}