How to request an injection in Android Fragments and Services?

I follow this guide to add Dagger 2 to my Android project.

After installing and creating modules and components, I can add dependencies to the Activity as follows:

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_account); ButterKnife.bind(this); ((AppController) getApplication()).getNetComponent().inject(this); } 

I'm struggling with how to inject dependencies in a fragment and IntentService?

 public class FragmentBrandList extends ListFragment { } 

In this class, in which @Override method @Override I request an injection and what will be the code for this?

+9
source share
6 answers

In this class, which @Override method should I use and what will be the code to add the dependency to the fragment?

The correct place to invoke embedding within a fragment is onAttach(Context context) . This is indicated in the section where to enter the Dagger 2 user manual here.

 @Override public void onAttach(Context context) { ((AppController) (context.getApplicationContext()).getNetComponent().inject(this); super.onAttach(context); } 

The correct place to call the injection inside the service is onCreate()

 @Override public void onCreate() { ((AppController) getApplication()).getNetComponent().inject(this); super.onCreate(); } 

Note that in both cases, the deployment request is before calling super.onCreate() . The Dagger User Guide explains it this way:

It is imperative to call AndroidInjection.inject () before super.onCreate () in the Activity, since the super call attaches the fragments from the previous instance of the Activity during a configuration change, which in turn injects the fragments. For successful implementation of the fragment, the action must already be entered. For ErrorProne users, a compiler error is to call AndroidInjection.inject () after super.onCreate ().

In other words:

  1. super.onCreate() Activity super.onCreate() reattaches fragments from the previous instance.
  2. This super call causes re-injection of the fragments (as fragments are injected into onAttach )
  3. Fragments must be embedded after their Activity, so request an injection in your Activity before calling super.onCreate() .

You can always check where to enter by looking at the appropriate source code for the com.google.dagger:dagger-android classes such as DaggerFragment and DaggerService . See the GitHub repository here

For your specific example, please make sure to add new deployment sites to NetComponent:

 void inject(FragmentBrandList frag); void inject(BrandListService service); 
+11
source

Step 1: Build 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: enter anywhere:

 DependencyInjector.applicationComponent() 

Your question inspired me to create a demo project that shows the operation, fragment and injection of a service using Dagger2. Here is git: https://github.com/write2sv/AndroidDIDagger2/tree/master/app/src/main/java/work/shaggy/didemo

+7
source

I did this using ((AppController) getActivity().getApplication()).getNetComponent().inject(this);

in Fragment.onCreate() .

+1
source

You can use Autadogger to avoid having to write this entire template. I often use this architecture:

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 } } 

Short description:

Your application module will have a β€œuniversal” dependency, but in this way you can achieve the use of several modules for the class. You just need to configure

 @AutoComponent( dependencies = YourApp.class, modules = { YourActivity.YourActivityModule.class, YourFragment.YourFragmentModule.class } ) 

block. You can add as many modules as you want using this syntax.

Hope this helps you

0
source

You just need to enable the injector method for what you want to enter.

 @Singleton @Component public interface AppComponent { void inject(MainActivity activity); void inject(FragmentBrandList fragmentBrandList); } 
0
source
 ((MyApp) context.getApplicationContext()).getApplicationComponent().inject(MyFragment.this); 

I added this in the onAttach(Context context) fragment method.

0
source

Source: https://habr.com/ru/post/1013474/


All Articles