Dagger 2: No implementation generated for component interface - android

I have created a demo Android Lib project and used dagger 2.0 with the following steps:
Added the following jars to /libs folder:
dagger-2.0.jar
dagger-compiler-2.0.jar
dagger-producers-2.0-beta.jar
guava-18.0.jar
javawriter-2.5.1.jar
javax.annotation-api-1.2.jar
javax.inject-1.jar
Project -> Properties -> Java Compiler -> Annotation Processing (Enabled annotation processing)
Project -> Properties -> Java Compiler -> Annotation Processing - Factory path: Added all the above mentioned jars.
Created the following classes:
public class Car {
private Engine engine;
#Inject
public Car(Engine engine) {
this.engine = engine;
}
public String carDetails(){
String engineName = this.engine.getName();
int engineNumber = this.engine.getNumber();
return "This car has the following details: \n" + engineName + "----" + engineNumber;
}
}
public interface Engine {
public String getName();
public int getNumber();
}
public class Toyota implements Engine{
#Override
public String getName() {
return "This is toyota engine";
}
#Override
public int getNumber() {
return 1234567890;
}
}
#Component(modules = EngineModule.class)
public interface EngineComponent {
void inject();
}
#Module
public class EngineModule {
public EngineModule(DemoApplication demoApplication) {
}
#Provides
Engine provideEngine(){
return new Toyota();
}
}
But inside /.apt-generated folder there are only two files:
Car_Factory.java EngineModule_ProvideEngineFactory.java
DaggerEngineComponent.java is not there for me to build the component.
Could someone please help?

I'm guessing the annotation processor is encountering an error and Eclipse is not showing you the log. If you have log output in the Output view, you may want to paste that into the question.
Specifically, I think it's erroring out on void inject(), which isn't a format descibed in the #Component docs. Those docs describe three types of methods:
Parameterless factory methods that return an injectable type Dagger creates and injects, like Engine createEngine(), or
Single-parameter void methods that receive an instance created elsewhere and apply method and field injection, like void injectEngine(Engine) or Engine injectEngine(Engine).
Subcomponent-returning methods that combine your Component's bindings with those from another module.
Because your void inject() doesn't match any of those formats, Dagger is likely erroring out and refusing to create a DaggerEngineComponent.

Related

Is that the correct way of creating realm module?

Hi i have a android project that use another android project as a module. I used realm for offline data storage. both the project uses realm data base. when i try to run the project it shows error.
class RealmModel is not part of the schema for this Realm
i used this link to fix that error
In that above url, they asked to create RealmModule class with #RealmModule annotation. This is my class,
#RealmModule
public class MessageRealmModule implements RealmModule {
#Override
public boolean library() {
return true;
}
#Override
public boolean allClasses() {
return false;
}
#Override
public Class<?>[] classes() {
return new Class<?>[0];
}
#Override
public Class<? extends Annotation> annotationType() {
return null;
}
}
After this line got this error.
java.lang.IllegalArgumentException: com.anubavam.message.MessageRealmModule is not a RealmModule. Add #RealmModule to the class definition.
No, you need to do it in the annotation parameters like so:
#RealmModule(library = true, classes = { MyModelClass.class })
public class MessageRealmModule {
}
See also https://realm.io/docs/java/latest/#schemas

Dagger 2.2 component builder module method deprecated

I started using dagger 2.2 and the module methods in the Component builder are deprecated.
This is my Application component :
#Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(Application application);
}
And the Application module:
#Module
public class ApplicationModule {
Application application;
public ApplicationModule(Application application) {
this.application = application;
}
#Provides
#Singleton
Application providesApplication() {
return application;
}
}
Here is the generated class:
#Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class DaggerApplicationComponent implements ApplicationComponent {
private DaggerApplicationComponent(Builder builder) {
assert builder != null;
}
public static Builder builder() {
return new Builder();
}
public static ApplicationComponent create() {
return builder().build();
}
#Override
public void inject(Application application) {
MembersInjectors.<Application>noOp().injectMembers(application);
}
public static final class Builder {
private Builder() {}
public ApplicationComponent build() {
return new DaggerApplicationComponent(this);
}
/**
* #deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://google.github.io/dagger/unused-modules.
*/
#Deprecated
public Builder applicationModule(ApplicationModule applicationModule) {
Preconditions.checkNotNull(applicationModule);
return this;
}
}
}
How do I initialize the component if not with the ComponentBuilder?
You should read the description of why it is deprecated. If you are using an IDE like IntelliJ or Android Studio you can just select the method and hit Control + Q on Windows to read the Javadoc including the deprecation notice.
The Javadoc reads:
#deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://google.github.io/dagger/unused-modules.
And from this link you can see:
When the Dagger processor generates components, it only requires instances of modules and component dependencies that are explicitly needed to supply requests for a binding.
If all of a module’s methods that are used in the component are static, Dagger does not need an instance of that module at all. Dagger can invoke the static methods directly without a module.
If a module provides no bindings for a Component, no instance of that module is necessary to construct the graph.
It is safe to say that you can just ignore the deprecation. It is intended to notify you of unused methods and modules. As soon as you actually require / use Application somewhere in your subgraph the module is going to be needed, and the deprecation warning will go away.
It show deprecated because you are not using Component and module in your application by
#Inject
SomeObjectFromModule mSomeObject
if you are not injecting dependencies in your applications there is no use of initialising your component so dagger look for at least one usage
once you add these lines in any classes you want to inject views and then clean build and rebuild the project and your deprecation will be solved
It showing error when my Module have no #Provides method or the object that provide by Dagger is not used in app.
Example to remove deprecated module
Module
#Module
public class SecondActivityModule {
#Provides
Book provideBookTest() {
return new Book();
}
}
Activity
public class SecondActivity extends AppCompatActivity {
#Inject
Book test;
...
}
OR in Component
#Component(modules = SecondModule.class)
public interface SecondComponent {
void inject(SecondActivity activity);
Book getBookTest();
}
I have the same problem with host and I just want everyone has deprecated issue on Generated component builder class should check two things to save time:
1/ Correct dagger syntax for module, component also check carefully where you inject.
2/ Must have injection object (inject annotation and its object) in place you want to inject or else the dagger compiler cannot see where to use your module so some method will be deprecated.Just inject at least one module's provides to your injection place and re-compile the code, you won't have that issue anymore :)
you will get module method deprecated if you declare void inject(AppCompactActivity activity); in component class. instead of you have to use tight coupling like following void inject(MainActivity activity);and rebuild your project you will see, there is no deprecate method in module class

Android Tests: use Dagger2 + Gradle

I understand how Dagger2 works,
I understand it allows to easily swap dependencies, so we can use mocks for testing.
Point is that I am not sure I understand how am I supposed to provide different Dagger2 Components implementations for testing and for debug/production.
Would I need to create 2 Gradle productFlavors (e.g "Production"/"Test")
that would contain 2 different Components definition?
Or can I specify that I want to use the mock Component for test compile and the non mock Component for non test builds?
I am confused, please some clarification would be great!
Thanks a lot!
Unit testing
Don’t use Dagger for unit testing
For testing a class with #Inject annotated constructor you don't need dagger. Instead create an instance using the constructor with fake or mock dependencies.
final class ThingDoer {
private final ThingGetter getter;
private final ThingPutter putter;
#Inject ThingDoer(ThingGetter getter, ThingPutter putter) {
this.getter = getter;
this.putter = putter;
}
String doTheThing(int howManyTimes) { /* … */ }
}
public class ThingDoerTest {
#Test
public void testDoTheThing() {
ThingDoer doer = new ThingDoer(fakeGetter, fakePutter);
assertEquals("done", doer.doTheThing(5));
}
}
Functional/integration/end-to-end testing
Functional/integration/end-to-end tests typically use the production
application, but substitute fakes[^fakes-not-mocks] for persistence,
backends, and auth systems, leaving the rest of the application to
operate normally. That approach lends itself to having one (or maybe a
small finite number) of test configurations, where the test
configuration replaces some of the bindings in the prod configuration.
You have two options here:
Option 1: Override bindings by subclassing modules
#Component(modules = {AuthModule.class, /* … */})
interface MyApplicationComponent { /* … */ }
#Module
class AuthModule {
#Provides AuthManager authManager(AuthManagerImpl impl) {
return impl;
}
}
class FakeAuthModule extends AuthModule {
#Override
AuthManager authManager(AuthManagerImpl impl) {
return new FakeAuthManager();
}
}
MyApplicationComponent testingComponent = DaggerMyApplicationComponent.builder()
.authModule(new FakeAuthModule())
.build();
Option 2: Separate component configurations
#Component(modules = {
OAuthModule.class, // real auth
FooServiceModule.class, // real backend
OtherApplicationModule.class,
/* … */ })
interface ProductionComponent {
Server server();
}
#Component(modules = {
FakeAuthModule.class, // fake auth
FakeFooServiceModule.class, // fake backend
OtherApplicationModule.class,
/* … */})
interface TestComponent extends ProductionComponent {
FakeAuthManager fakeAuthManager();
FakeFooService fakeFooService();
}
More about it in the official documentation testing page.

Is this the correct way of adding parammeters to constructor in Dagger 2?

Context
Recenty I started investigating about dependency injection and Dagger 2. It looks a pretty good library but it seems a bit confusing to me. There are some situations in which I don't know exactly how to proceed.
What have I tried
I have created a simple Android app that creates a Client and its Dependency and do some (dummy) work. These are the classes:
Client.java
public class Client {
private Dependency dep;
#Inject
public Client(Dependency dep) {
this.dep = dep;
}
public void work() {
System.out.println("Client working");
dep.doWork();
}
}
Dependency.java
public class Dependency {
#Inject
public Dependency() {
}
public void doWork() {
System.out.println("Dependency working");
}
}
Following some tutorials I created a couple of Module classes:
DependencyModule.java
#Module
public class DependencyModule {
#Provides
Dependency provideDependency() {
return new Dependency();
}
}
ClientModule.java
#Module
public class ClientModule {
#Provides
Client provideClient(Dependency dep) {
return new Client(dep);
}
}
And also the Component interface:
#Component(modules = {ClientModule.class})
public interface ClientComponent {
Client provideClient();
}
This works fine. From my activity I can do the following and it works:
ClientComponent clientComp = DaggerClientComponent
.builder()
.clientModule(new ClientModule())
.build();
Client client = clientComp.provideClient();
client.work();
Problem
I understand how to inject dependencies in a client (at least I think so). But how I add parameters into the constructor of a client/dependency?
I mean, what if I would wanted to add some int parameters to my objects? Something as simple as this:
Client.java
public class Client {
int id;
Dependency dep;
#Inject
public Client(int id, Dependency dep) {
this.id = id;
this.dep = dep;
}
public void work() {
System.out.println("id: " + id + " Client working");
dep.doWork();
}
}
Dependency.java
public class Dependency {
private int id;
#Inject
public Dependency(int id) {
this.id = id;
}
public void doWork() {
System.out.println("id: " + id + " Dependency working");
}
}
NOTE:
The following code is what I've tried. So I'm not sure about its correctness.
So, as the objects has new parameters in their constructor the Modules have to change:
DependencyModule.class
public class DependencyModule {
#Provides
Dependency provideDependency() {
return new Dependency(id);
}
}
ClientModule.class
#Module
public class ClientModule {
#Provides
Client provideClient(int id, Dependency dep) {
return new Client(id, dep);
}
}
Question
How do I use that new Modules? I haven't found a way to pass the id to that methods. The only way I get it to work is by passing it in the Module constructor and removing it from the provide method. This way:
#Module
public class ClientModule {
private int id;
public ClientModule(int id) {
this.id = id;
}
#Provides
Client provideClient(Dependency dep) {
return new Client(id, dep);
}
}
Same approach in the DependencyModule.java.
This way, adding the DependencyModule.class in the ClientComponent interface I can do something like:
ClientComponent clientComp = DaggerClientComponent
.builder()
.clientModule(new ClientModule(clientId))
.dependencyModule(new DependencyModule(dependencyId))
.build();
Client client = clientComp.provideClient();
client.work();
Is that the correct way of doing that?
Is there a better way of getting the same effect?
Am I committing crimes against DI principle?
There are two basic ways to get Dagger to provide an instance of a class:
Add #Inject to a constructor, and put the class's dependencies in as constructor arguments.
Add a #Provides-annotated method to a #Module-annotated class, and install that module into your #Component.
You only need to use one method for each class. So in your first example, Client and Dependency are fine as is; you don't also need ClientModule and DependencyModule.
Once you add the int dependency, now you do need a module, because there's no class to #Inject. The module just needs to provide that int, so something like this would work:
#Module
public class ClientIdModule {
private final clientId;
public ClientIdModule(int clientId) {
this.clientId = clientId;
}
#Provides
static int clientId() {
return clientId;
}
}
Now if you install ClientIdModule into your component, you'll be able to get a Client which has the right ID, and its Dependency will as well.

how can I inject a dependency in a method?

I'm a beginner with dependency injection.. specifically Dagger 2. I'm trying to figure out if/how I can do something like this:
#Inject
public void someMethodName(int someInteger, SomeObject dependency){
// do something with the dependency.
}
Or do I need to put that dependency in as a class var? any help with this would be greatly appreciated. also in this case the variable someInteger is not a dependency, but is being added by the caller... does that matter?
can I call it like this:
this.someMethodName(5);
android studio does not like the above calling method (I'm assuming because I'm doing something wrong)
You need to create component which is annotated by #Component.
The Component accepts module which provides dependencies.
Every component's name that you create starts with Dagger prefix, e.g. for MyComponent.
Let's look at the following example:
#Singleton
#Component(modules = DemoApplicationModule.class)
public interface ApplicationComponent {
void inject(DemoApplication application);
}
We created ApplicationComponent with single injection method. What we're saying is that we want to inject certain dependencies in DemoApplication.
Moreover, in the #Component annotations we specify module with provision methods.
This is like our module looks like:
#Module
public class DemoApplicationModule {
private final Application application;
public DemoApplicationModule(Application application) {
this.application = application;
}
#Provides #Singleton SomeIntegerHandler provideIntegerHandler() {
return new MySomeIntegerHandlerImpl();
}
}
What we're saying by creating DemoApplicationModule is that the module can provide desired dependencies in the injection place specified by our Component.
public class DemoApplication extends Application {
private ApplicationComponent applicationComponent;
#Inject SomeIntegerHandler handler;
#Override public void onCreate() {
super.onCreate();
applicationComponent = DaggerApplicationComponent.builder()
.demoApplicationModule(new DemoApplicationModule(this))
.build();
applicationComponent.inject(this);
handler.someMethodName(5);
}
}
See documentation what you kind of dependencies you can obtain. Additionally to obtaining just raw instance you can obtain Provider, Factory or Lazy instance.
http://google.github.io/dagger/api/latest/dagger/Component.html
You can also create scoped dependencis, the lifecycles of which depend on the lifecycle of injection places, like Activities or Fragments.
Hope I gave you the basic notion of what Dagger is.
YOU CAN USE SOME INTERFACE
public interface myDependence{
int myFunction(int value);
}
NOW IMPLEMENT IN YOU CLASS
public myClass implements MyDependence{
#Override
int myFunction(int value){
// do something
}
}

Categories

Resources