Closed pzmudzinski closed 6 years ago
Here's my solution:
Make Application implements HasServiceInjector and inject a DispatchingAndroidInjector for services.
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;
}
}
Create a new module to perform injection over your services.
@Module
abstract class ServiceBuilderModule {
@ContributesAndroidInjector
abstract MyService contributeMyService();
}
Register your new module in your application's 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);
}
And finally, override method onCreate of the service adding AndroidInjection.inject(this).
public class MyService extends Service {
@Override
public void onCreate() {
AndroidInjection.inject(this);
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Ok, but what about integration tests? It will crash since Github example app is using different Application
class which disables Dagger initialization and you are responsible for manually providing mock-objects into properties.
This is a Dagger question, not an Architecture Components question. Closing as off-topic
Yup it did solve my problem
@Nauce, Does it matter where Dagger is injected in the Service
class, before or after super.onCreate()
, or is it similar to a fragment in that Dagger can be injected before or after the super
call?
@AdamSHurwitz , it should be done before super.onCreate()
.
This code version is outdated. Take a look into Dagger classes to extend from them, like DaggerService.
Thanks @Nauce.
Is the reasoning similar to activity injection which the documentation explains:
...to avoid issues with fragment restoration. During the restore phase in
super.onCreate()
, an activity attaches fragments that might want to access activity bindings.
@AdamSHurwitz, you are welcome. It could be done before or after calling super.onCreate()
like in Fragment
(there are not lifecycle problems), but constructor injection is preferred whenever possible to ensure that no field is referenced before it has been set, which helps avoid NullPointerExceptions.
For example, a class can extend from a parent class that runs one of the dependencies before injecting them.
Fragment & Activity injection is done through
registerActivityLifecycleCallbacks
andregisterFragmentLifecycleCallbacks
, but it's unclear how to turn on injection forServices
. Any ideas?