Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Dagger 2 to inject into service

I have an app which is basically a service that runs all the time and alarms the user when something happens.

When the service creates the alarm, it needs to give it his context so that the alarm can do callbacks to the service when something happens.

For example:

public MyService extends Service{     private SomeAlarm alarm;      @Override     public void onCreate() {         super.onCreate();         alarm = new SomeAlarm(MyService.this);     } } 

How can I inject the SomeAlarm class into the service, and give the SomeAlarm the service context as a variable?

like image 587
Ofek Agmon Avatar asked May 05 '16 13:05

Ofek Agmon


People also ask

How do you inject an activity Dagger?

To inject an object in the activity, you'd use the appComponent defined in your Application class and call the inject() method, passing in an instance of the activity that requests injection. When using activities, inject Dagger in the activity's onCreate() method before calling super.

What does @inject do Dagger?

Declaring Dependencies Inject annotation to identify which constructors and fields it is interested in. Use @Inject to annotate the constructor that Dagger should use to create instances of a class.

How do you inject value at runtime in Dagger?

Inject values at runtime with UI in Dagger2:pureMathModule("Book Name") . build() . inject(this); The difference between DaggerComponent create() and in build() is - create() works when no runtime argument is passed into the constructor, else we use build() method.


2 Answers

I wrote the code from the top of my head, so there could be a typo or two.

You do it just the same as when injecting stuff into activities.

  1. Declare a component,
  2. add the inject method to that component,
  3. add a module providing your service
  4. create that components builder
  5. add your module to the builder
  6. inject your service with the component

Your module and component would look something like this (maybe add some scope)

@Module class ServiceModule {      MyService mService;      ServiceModule(MyService service) {         mService = service;     }      @Provides     MyService provideMyService() {         return mService;     } }  @Component(modules=ServiceModule.class) interface MyServiceComponent {     void inject(MyService service); } 

Then in onCreate just create your component and inject your alarm.

@Inject private SomeAlarm alarm;  public void onCreate() {     DaggerMyServiceComponent.builder()             .serviceModule(new ServiceModule(this))             .build()             .inject(this);      alarm.doStuff(); } 

This is assuming that your alarm can be constructor injected by having an @Inject annotated constructor like this:

class SomeAlarm {     @Inject     SomeAlarm(MyService service) {         /*constructor stuff*/     } } 

Else you would just also add the alarm creation to your module.

like image 158
David Medenjak Avatar answered Sep 21 '22 06:09

David Medenjak


I know this question already has an answer but there are an other way to do this

first make your application extend HasServiceInjector like this:

public class App extends Application implements HasActivityInjector,  HasServiceInjector {  @Inject DispatchingAndroidInjector<Activity> dispatchingActivityInjector; @Inject DispatchingAndroidInjector<Service> dispatchingServiceInjector;  @Override public void onCreate() {     super.onCreate();     AppInjector.init(this); }  @Override public AndroidInjector<Activity> activityInjector() {     return dispatchingActivityInjector; }  @Override public AndroidInjector<Service> serviceInjector() {     return dispatchingServiceInjector; }  } 

then create a ServiceBuilderModule this will perform injection over services:

@Module abstract class ServiceBuilderModule {  @ContributesAndroidInjector abstract MyService contributeMyService();  } 

then register the new module to your component

@Component(modules = {     AndroidSupportInjectionModule.class,     AppModule.class,     ActivityBuilderModule.class,     ServiceBuilderModule.class  })  @Singleton  public interface AppComponent {   @Component.Builder  interface Builder {     @BindsInstance     Builder application(App application);      AppComponent build();  }   void inject(App app);   } 

then override the onCreate method of your service and add AndroidInjection.inject(this) like below code :

public class MyService extends Service {  @Override public void onCreate() {     AndroidInjection.inject(this);     super.onCreate(); }  @Nullable @Override public IBinder onBind(Intent intent) {     return null; }  } 

code in kotlin is exact conversion of the code above. hope this helps some coders from now on.

like image 35
Pouya Danesh Avatar answered Sep 25 '22 06:09

Pouya Danesh