I'm following this tutorial to add Dagger 2 to my Android project.
After doing setup and creating the modules and components I can add the dependencies in an Activity like this:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account);
ButterKnife.bind(this);
((AppController) getApplication()).getNetComponent().inject(this);
}
I am struggling in how to inject dependencies in a Fragment and IntentService?
public class FragmentBrandList extends ListFragment {
}
In this class which @Override
method should I request injection in and what will be the code for this?
In this class which @Override method i should use and what will be the code to add dependency in fragment?
The correct place to call injection inside a Fragment is onAttach(Context context)
. This is stated in the where to inject section of the Dagger 2 user guide here
@Override
public void onAttach(Context context) {
((AppController) context.getApplicationContext()).getNetComponent().inject(this);
super.onAttach(context);
}
The correct place to call injection inside a Service is onCreate()
@Override
public void onCreate() {
((AppController) getApplication()).getNetComponent().inject(this);
super.onCreate();
}
Note that in both cases the request for injection comes before the call to super.onCreate()
. The Dagger user guide explains it like this:
It is crucial to call AndroidInjection.inject() before super.onCreate() in an Activity, since the call to super attaches Fragments from the previous activity instance during configuration change, which in turn injects the Fragments. In order for the Fragment injection to succeed, the Activity must already be injected. For users of ErrorProne, it is a compiler error to call AndroidInjection.inject() after super.onCreate().
In other words:
super.onCreate()
call re-attaches Fragments from a previous instance super
call in cause Fragments to be re-injected (since Fragments are injected in onAttach
) super.onCreate()
. You can always check where to inject by looking at the relevant source code for the com.google.dagger:dagger-android
classes like DaggerFragment
and DaggerService
. See the GitHub repo here
For your specific example, please make sure you have added the new injection sites to the NetComponent:
void inject(FragmentBrandList frag);
void inject(BrandListService service);
Step 1: Create your 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");
}
}
Step 2: Create your 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);
}
Step 3: Create a DI Class:
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(){}
}
Final Step: Inject anywhere using:
DependencyInjector.applicationComponent()
Your question inspired me to create a Demo project that shows Activity, Fragment and Service injection using Dagger2. Here is the git: https://github.com/write2sv/AndroidDIDagger2/tree/master/app/src/main/java/work/shaggy/didemo
I did it using ((AppController) getActivity().getApplication()).getNetComponent().inject(this);
in Fragment.onCreate()
method.
You can use autodagger2 to avoid having to write all that boilerplate. I use this architecture quite often:
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
}
}
Quick explanation:
Your app's module will have to a "universal" dependency, but this way you can achieve using several modules for a class. You just need to customize the
@AutoComponent(
dependencies = YourApp.class,
modules = { YourActivity.YourActivityModule.class, YourFragment.YourFragmentModule.class }
)
block. You can add as many modules as you like using that syntax.
Hope this helps you
You really just need to include the injector method for whatever you want to inject.
@Singleton
@Component
public interface AppComponent {
void inject(MainActivity activity);
void inject(FragmentBrandList fragmentBrandList);
}
((MyApp) context.getApplicationContext()).getApplicationComponent().inject(MyFragment.this);
我在onAttach(Context context)
方法中添加了这个。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.