I'm currently trying to add Dagger to my android projects. For the apps projects its easy and clear to me, how to build the ObjectGraph. But I dont quite know whats the best way to do this in my android library projects.
Should I keep building the ObjectGraph in the Application class of the apps and pass the OG over to a LibraryModule - plussing the OG of library to the Apps OG? Or should i build the whole ObjectGraph in the library?
What if I need to inject a class in the library by ObjectGraph.inject(this)? In my Apps projects I can get the OG from the Application class. But how to handle this in the library? Should I add a #Provides method for the ObjectGraph?
Big thanks for your help.
Edit:
In short: How can I call ObjectGraph.inject(this) in my library project where I don't have access to the OG because it is being builded in the Application Class?
In case someone using Dagger 2 gets here, this is the way I've done in my App:
In the library module I've created the following Module and Component:
#Module
public class ModuleUtil {
#Provides
public RestTemplate provideRestTemplate() {
return new RestTemplate();
}
}
#Singleton
#Component(
modules = {
ModuleUtil.class
})
public interface MainComponent {
void inject(Postman postman);
}
And then I've created the Singleton below in order to manage the injections:
public class DaggerWrapper {
private static MainComponent mComponent;
public static MainComponent getComponent() {
if (mComponent == null) {
initComponent();
}
return mComponent;
}
private static void initComponent () {
mComponent = DaggerMainComponent
.builder()
.utilModule(new ModuleUtil())
.build();
}
}
When some class from the library module needs to inject its members, I simply call DaggerWrapper.getComponent().inject(this); and that't it.
I'm doing this way:
#Module classes belong to the main project and they provide implementations which you are injecting to library elements, so there are no #Module classes in the library projects
Library elements which are expecting dependency must have access to ObjectGraph and call .inject() on themselves, but main project should give ObjectGraph instance to the library with provided #Module dependency
How to get ObjectGraph from main project into the library? You could have interface like this:
interface Injector {
void inject(Object object);
public ObjectGraph getObjectGraph();
}
Context objects like Activity or Application class implements this interface (holders of ObjectGraph objects).
If you have example of Activity in the library module which needs something to inject from the main project this would look like this:
class LibraryActivity extends Activity {
#Inject ActivationModule instance;
void onCreate(... ) {
Injector injector = (Injector)getApplicationContext();
injector.inject(this)
}
}
ActivationModule is the class/interface in the library project.
Main project has application class which implements Injector interface and creates ObjectGraph with provided dependecy for ActivationModule in the library project.
class MyApplicationInTheMainProject extends Application implements Injector {
ObjectGraph graph;
#Override
public void onCreate() {
super.onCreate();
graph = ObjectGraph.create(new ActivationModuleImpl(this));
}
#Override public void inject(Object object) {
graph.inject(object);
}
#Override public ObjectGraph getObjectGraph() {
return graph;
}
}
#Module(injects = {
LibraryActivity.class
}, library = true)
class ActivationModuleImpl implements ActivationModule {
....
}
if you are giving this library to people and they dont know nothing about your scenario so you must write it in a way that your Dagger works perfectly without any help from user. (the easier to work with the better practice)
i just wrote some library for you to show how to do it. i wrote the library in a way that you can even run it standalone and see the result in the messages tab. user of your library doesnt need to know nothing about dagger and does nothing he just uses the library and dagger will be configured:
https://github.com/amirziaratii/libraryUsingDagger.git
if this library is something you use it yourself and for your own project, the best practice is do it like in this project of my friend:
https://github.com/mmirhoseini/trakt.tv
all your questions are answered in these two projects. ask any question and ill answer in comment.
Related
I'm using Dagger across several Gradle modules in an android project. I have a lib and app module. Inside lib module I have two classes PrivateThing and ExposedThing. ExposedThing depends on PrivateThing.
I have a dagger #Module to provide these two things:
#Module
public class LibModule {
#Provides
ExposedThing provideExposedThing(PrivateThing privateThing) {
return new ExposedThing(privateThing);
}
#Provides
PrivateThing providePrivateThing() {
return new PrivateThing();
}
}
In the app module, I have a single class SomeUiElement which depends on ExposedThing and a separate module:
#Module
public class ApplicationModule {
#Provides
SomeUiElement provideSomeUiElement(ExposedThing exposedThing) {
return new SomeUiElement(exposedThing);
}
}
And a component to bring everything together:
#Singleton
#Component(modules = {
ApplicationModule.class,
LibModule.class
})
public interface ApplicationComponent {
void inject(SomeActivity activity);
}
Now I want to enforce that nothing in the app module can depend on PrivateThing. I think I'm asking something similar to this question. One solution was to use component dependency. However the documentation recommends subcomponents see "Subcomponents for encapsulation".
Which is the preferred way to do this? Won't either method mean that lib module supplies it's own Component? I thought this was not a best practice, that libraries should only supply a Module.
I started working on a new Android project from scratch. After understanding the project scope and requested features, I've came up with a modular architecture (basically wrapping every feature into a feature or android module) that looks as following
Everything looks perfect until I wanted to introduce dagger to glue all the modules. The problem is that I want every module to has its own dagger component/subcomponent and it's modules in order to provide dependencies and expose them the graph to be using by other component or the parent one.
Google official dagger documentation states that subcomponents has direct access to parent component dependencies' and not vice versa. However, in my case the base component require dependencies from the data module and this latter itself require dependencies from the network module.
is there any solution for this problem knowing that i want every android module to have its own sub-component preferably? If not, is there any solution anyway?
Thank you.
Edit:
Here is how my project structure looks like
And this is how I setup my dagger graph
My AppComponent(Dagger root)
#Singleton
#Component(modules = {
AppModule.class,
ActivityBuilder.class,
AndroidSupportInjectionModule.class
})
public interface AppComponent {
void inject(CatApp application);
#Component.Builder
interface Builder {
#BindsInstance
Builder application(Application application);
AppComponent build();
}
}
My App Module
#Module(subcomponents = DataComponent.class)
public class AppModule {
#Provides
#Singleton
Context provideContext(Application application) {
return application.getApplicationContext();
}
}
My DataComponent (located at the data android module)
#Subcomponent(modules = DataModule.class)
public interface DataComponent {
#Subcomponent.Builder
interface Builder {
DataComponent build();
}
}
Data module (located at data android module) that should provide the implementation of SystemManager
#Module(subcomponents = NetworkComponent.class)
public class DataModule {
#Provides
#Singleton
ISystemManager provideSystemManager(SystemManager systemManager) {
return systemManager;
}
}
Network Component (located at Network Android Module)
#Subcomponent(modules = NetworkModule.class)
public interface NetworkComponent {
#Subcomponent.Builder
interface Builder {
NetworkComponent build();
}
}
Network Module (located at Network Android Module) and should provide implementation of INetWorkManager
#Module
public class NetworkModule {
#Provides
#Singleton
INetworkManager provideNetworkManager(NetworkManager networkManager) {
return networkManager;
}
}
I am using #Inject annotation at all constructors so my configurations is all setup but the issue is that dagger doesn't compiles these subcomponent for some reason and I get this error when compiled:
Error:(27, 8) error: [dagger.android.AndroidInjector.inject(T)] com.github.andromedcodes.network.INetworkManager cannot be provided without an #Provides-annotated method.
com.github.andromedcodes.network.INetworkManager is injected at
com.github.andromedcodes.data.SystemManager.<init>(networkManager)
com.github.andromedcodes.data.SystemManager is injected at
com.github.andromedcodes.data.di.DataModule.provideSystemManager(systemManager)
com.github.andromedcodes.domain.managers.ISystemManager is injected at
com.github.andromedcodes.domain.interactors.CheckSystemAvailability.<init>(systemManager)
com.github.andromedcodes.domain.interactors.CheckSystemAvailability is injected at
com.github.andromedcodes.chasseautrsor.views.Splash.SplashPresenter.<init>(checkSystemAvailability)
com.github.andromedcodes.chasseautrsor.views.Splash.SplashPresenter is injected at
com.github.andromedcodes.chasseautrsor.di.SplashModule.bindSplashPresenter(presenter)
com.github.andromedcodes.chasseautrsor.views.Contract.Presenter is injected at
com.github.andromedcodes.mvp.BaseActivity.mPresenter
com.github.andromedcodes.chasseautrsor.views.SplashScreenActivity is injected at
dagger.android.AndroidInjector.inject(arg0)
How can I fix this issue knowing that I want to provide ISystemManager implementation at Data android Module and INetworkManager at Network Android Module?
Thank you.
Subcomponents automatically have access to objects bound in the parent components' graph, which makes sense, because subcomponents have exactly one parent component—there's no ambiguity. Parent components do not have automatic access to subcomponents' graph because you can create as many subcomponent instances as you'd like; it's not clear which instance you're trying to access. In general, unless you need different variations on an object graph (which you'd do with private modules or child injectors in Guice) or unless you wanted to hide implementation details (e.g. internal network objects), you may be better off installing your modules all in the same Component and skipping the subcomponent strategy.
However, if you do want to separate your graph or create multiple subcomponent instances, you could also create a subcomponent instance in a scoped #Provides method. That way NetworkComponent has a separate graph with private bindings, but can also use dependencies you expose in AppComponent, and you can also ensure that there is exactly one copy of NetworkComponent and its relevant bindings in your graph. You'll also need to put a getter (provision method or factory method) on the Subcomponent, so you can access some of its bindings from outside, in exactly the same way that you need a getter or injector method on a #Component for it to be useful.
#Subcomponent(modules = NetworkModule.class)
public interface NetworkComponent {
/** Allow anyone with a NetworkComponent instance to get the INetworkManager. */
INetworkManager getINetworkManager();
#Subcomponent.Builder
interface Builder {
NetworkComponent build();
}
}
/**
* Creates a singleton NetworkComponent. Install this in AppComponent's module,
* or in your data module if that encapsulates network calls.
*/
#Singleton #Provides NetworkComponent networkComponent(
NetworkComponent.Builder builder) {
return builder.build();
}
/** Make the INetworkManager accessible, but not the NetworkManager impl. */
#Provides static provideNetworkManager(NetworkComponent networkComponent) {
return networkComponent.getINetworkManager(); // add this to NetworkComponent
}
For further reference, see the "Subcomponents for Encapsulation" section on in the Dagger 2 docs on Subcomponents:
Another reason to use subcomponents is to encapsulate different parts of your application from each other. For example, if two services in your server (or two screens in your application) share some bindings, say those used for authentication and authorization, but each have other bindings that really have nothing to do with each other, it might make sense to create separate subcomponents for each service or screen, and to put the shared bindings into the parent component.
In the following example, the Database is provided within the #Singleton component, but all of its implementation details are encapsulated within the DatabaseComponent. Rest assured that no UI will have access to the DatabaseConnectionPool to schedule their own queries without going through the Database since that binding only exists in the subcomponent.
I have a project that provides an interface, let's call it IImplementMe, which i want to inject into my project. This interface will be implemented by various producers, so I need to inject all implementations. I am trying to use TypeLiteral for this.
Here is the code of the producer :
#Singleton
public class SomeImplementation implements IImplementMe {
private final String value;
#Inject
public SomeImplementation(final SomeOtherConfig configuration) {
this.value= configuration.getValue();
}
#Override
public String getValue() {
return value;
}
}
And in my registry class I have register(IImplementMe.class).to(SomeImplementation.class);
Then, in my project I inject it like this :
#Inject
public SomeEndpoint(final List<IImplementMe> implementations){
///
}
and i bind it like
private static class MarketDataSetTypeLiteral extends TypeLiteral<List<IImplementMe>> {
}
bind(new MarketDataSetTypeLiteral()).toRegistry();
I made sure my SomeIMplementation constructor gets called, but in my endpoint the List is empty, so no implementation is provided. I'm using guice for injection. Any ideas ?
LE: It turns out that the provided implementation is created after my endpoint class is created (at creation time it injects a reference of an empty list). Later in the lifecycle the reference is updated with the implementation, so I actually have access to it after guice does it's stuff.
I'm guessing it's due to the maven dependencies, and how guice handles the instantiations. Since the producer must have a dependency on my project, I guess it makes sense it gets instantiated last, thus causing my initial problem.
You are looking for multibindings -> https://github.com/google/guice/wiki/Multibindings
public class IImplementMeModule extends AbstractModule {
public void configure() {
Multibinder< IImplementMe > uriBinder = Multibinder.newSetBinder(binder(), IImplementMe.class);
uriBinder.addBinding().to(SomeImplementationOfIImplementMe.class);
uriBinder.addBinding().to(AnotherImplementationOfIImplementMe.class);
... // bind plugin dependencies, such as our Flickr API key
}
}
Then you can inject the set of IImplemetnMe as following
#Inject TweetPrettifier(Set<IImplemetnMe> implementations)
I would suggest you to have a look at MapBindings which allows you provide keys for each implementation and then you will be able to inject your bindings as a Map
I'm having a project based on Dagger 2 which consists of two modules. The core module includes some interfaces and some classes that have member injections declared for these interfaces.
The actual implementations of these interfaces are included in the second module which is an Android project. So, naturally the provide methods for these are included in the Android project.
Dagger will complain during compilation about not knowing how to inject these in the core module.
Any thoughts on how to achieve this without using constructor injections?
In short, I just tried this, and it works. Be sure to check the exact error messages and make sure you are providing these interfaces and #Inject annotations are present.
There is probably just some wrong named interface or a missing annotation. Following up is a full sample using your described architecture that is compiling just fine. The issue you are currently experiencing is probably the one described in the last part of this post. If possible, you should go with the first solution though and just add those annotations.
The library
For reproducability this sample has minimalist models. First, the interface needed by my class in the library module:
public interface MyInterface {
}
Here is my class that needs that interface. Make sure to declare it in the constructor and provide the #Inject annotation!
#MyScope // be sure to add scopes in your class if you use constructor injection!
public class MyClassUsingMyInterface {
private MyInterface mMyInterface;
#Inject
public MyClassUsingMyInterface(MyInterface myInterface) {
mMyInterface = myInterface;
}
}
The idea is that the interface will be implemented by the app using MyClassUsingMyInterface and provided by dagger. The code is nicely decoupled, and my awesome library with not so many features is complete.
The application
Here need to supply the actual coupling. This means to get MyClassUsingMyInterface we have to make sure we can supply MyInterface. Let's start with the module supplying that:
#Module
public class MyModule {
#Provides
MyInterface providesMyInterface() {
return new MyInterface() {
// my super awesome implementation. MIT license applies.
};
}
}
And to actually use this, we provide a component that can inject into MyTestInjectedClass that is going to need MyClassUsingMyInterface.
#Component(modules = MyModule.class)
public interface MyComponent {
void inject(MyTestInjectedClass testClass);
}
Now we have a way to provide the requested interface. We declared that interface needed by the library class in a constructor marked with #Inject. Now I want a class that requires my awesome library class to use. And I want to inject it with dagger.
public class MyTestInjectedClass {
#Inject
MyClassUsingMyInterface mMyClassUsingMyInterface;
void onStart() {
DaggerMyComponent.create().inject(this);
}
}
Now we hit compile...and dagger will create all the factories needed.
Inject Libraries you can not modify
To just provide the full scale of dagger, this sample could also have been without actual access to the source code of the library. If there is no #Inject annotation dagger will have a hard time creating the object. Notice the missing annotation:
public class MyClassUsingMyInterface {
private MyInterface mMyInterface;
public MyClassUsingMyInterface(MyInterface myInterface) {
mMyInterface = myInterface;
}
}
In that case we have to manually provide the class. The module would be needed to be modified like the following:
#Module
public class MyModule {
#Provides
MyInterface providesMyInterface() {
return new MyInterface() {
};
}
#Provides
MyClassUsingMyInterface providesMyClass(MyInterface myInterface) {
return new MyClassUsingMyInterface(myInterface);
}
}
This introduces more code for us to write, but will make those classes available that you can not modify.
i have two independent projects Basic and Extension with following setup
Project A:
class Handler {
public void handle(){
...
}
}
Project B
import Handler; //from Proejct A
class SomeClass{
someMethod() {
handle(); //dependency to Project As class with handle method
}
}
So the problem is the dependecy to the handle method which exists at Project A but not at compile time on Project B.
The final step is to have build Project Extension as a jar and import it inside Project Basic.
Ofc the compiler will give me error when i build Project B since the handle is not known at compile time.
For this issue i need a solution:
Either: Tell java that the missing code (import class with handle method) will be there at running time.
Or maybe Dependency Injection due to a factory pattern.
I am known to the factory pattern, but i don't understand how it could help me in this situation.
Or another solution.
Can you help me?
Neither of these are valid Java - won't compile. The proper keyword is "class", not "Class".
You have to provide it at compile time once you get it right - you have no choice. No way around it.
Maybe you should look at the Java JDK and follow the example in the java.sql package: Interfaces. Connection, ResultSet, Statement, etc. are all interfaces so vendors can provide their own implementations. Users only deal with interfaces.
Your GenericHandler should be an interface that you provide to clients. They add their implementations and add their JAR file containing the custom implementation at runtime.
Basic interface that all extensions implement:
public interface GenericHandler {
void genericHandle();
}
Extension code:
import GenericHandler;
public class Extension implements GenericHandler {
public void genericHandle() {
// Do something useful here
}
}
The factory pattern works only if you provide a finite, closed set of implementations:
public class GenericHandlerFactory {
private final GenericHandlerFactory instance = new GenericHandlerFactory();
private GenericHandlerFactory() {}
public GenericHandler getInstance() { return this.instance; }
public GenericHandler createHandler(Class genericHandlerClass) {
GenericHandler result = null;
// Code to create the GenericHandler you want.
return result;
}
}
If users can extend your interface without your knowledge then a factory can't work; you have to stick to the JDBC example.