Hi im trying to figure out how to do a clean third party injection. I want to inject Otto bus properly into my services and activities.
Iv seen that you can use inject on constructor, but since I dont have any constructor with Android, i wonder how I can then inject my bus.
Iv created a module which provides a new instance of the bus. Iv also created a component which has an interface for the Bus object.
But how can I get this injected and where should I initiate my graph?
Since the objectGraph from Dagger 1 is removed, i use the Dagger_.... component and create() in the application class, but how should I inject it into whatever activity or service?
Should I create the component in every onCreate and get the bus from there? Or is it possible to @Inject like Dagger 1? Please tell me because right now it seems much more clumpy and complicated than Dagger 1 way of doing it.
@Component(modules = EventBusModule.class)
@Singleton
public interface EventBus {
Bus bus();
}
@Module
public class EventBusModule {
@Provides
@Singleton
public Bus provideBus() {
return new Bus(ThreadEnforcer.ANY);
}
}
All i want to be able to do is:
public class WearService extends WearableListenerService {
private static final String TAG = WearService.class.getSimpleName();
@Inject
protected Bus bus;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
bus.register(this);
return START_STICKY;
}
}
I look at this example(https://github.com/LiveTyping/u2020-mvp) and see that its possible, but not sure how things is hanging together.
It is quite usual to instantiate the Dagger component in the Application
instance. Since you probably don't have a reference to your WearService
from your Application
class, you'll need to make the WearService
ask your Application
to provide the Bus
.
You can do this in two ways:
By adding an inject(WearService wearService)
method to your EventBus
component:
@Component(modules = EventBusModule.class)
@Singleton
public interface EventBus {
Bus bus();
void inject(WearService wearService);
}
You can now keep a reference to your Component in your Application
:
public class MyApplication extends Application {
private EventBus mEventBusComponent;
@Override
public void onCreate() {
super.onCreate();
mEventBusComponent = Dagger_EventBus.create();
}
public void inject(WearService wearService) {
mEventBusComponent.inject(wearService);
}
}
From your WearService
, ask your Application
to inject it:
public class WearService extends WearableListenerService {
private static final String TAG = WearService.class.getSimpleName();
@Inject
protected Bus bus;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
((MyApplication) getApplicationContext()).inject(this);
bus.register(this);
return START_STICKY;
}
}
By retrieving the Bus
manually. Add a getter method for the EventBus
component in the Application
:
public class MyApplication extends Application {
private EventBus mEventBusComponent;
@Override
public void onCreate() {
super.onCreate();
mEventBusComponent = Dagger_EventBus.create();
}
public EventBus getEventBusComponent() {
return mEventBusComponent;
}
}
Then, in your WearService
, call the bus()
method:
public class WearService extends WearableListenerService {
private static final String TAG = WearService.class.getSimpleName();
private Bus bus;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
bus = ((MyApplication) getApplicationContext()).getEventBusModule().bus();
bus.register(this);
return START_STICKY;
}
}
For injecting the Bus
into classes you can instantiate, you can use constructor injection:
public class MyClass() {
private final Bus mBus;
@Inject
public MyClass(final Bus bus) {
mBus = bus;
}
}
Since Dagger knows how to create a Bus
instance (because of your @Provides
method), Dagger will now also know how to create a MyClass
instance, no @Provides
method necessary. For example, this will work:
public class WearService extends WearableListenerService {
private static final String TAG = WearService.class.getSimpleName();
@Inject
protected Bus bus;
@Inject
protected MyClass myClass;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
((MyApplication) getApplicationContext()).inject(this);
bus.register(this);
return START_STICKY;
}
}
The MyClass
instance will automatically be created for you, with the same instance of Bus
(since it is marked as @Singleton
).
After some discususins with Niek regarding my question, I went to the source to find my answer. I asked on the github repo of dagger 2, and the answer can be found here:
https://github.com/google/dagger/issues/128#issuecomment-86702574
Its very deliberate and posts different solutions to my issue.