1

I'm using Dagger for Android for dependency injections. I have a UserService object in a Main Class:

public class Main implements Runnable {

@Inject
UserService service;

@Override
public void run() {
    for (User f : service.getUserByName("toto")) {
        System.out.print(f.getM_Nom());
    }
}

public static void main(String[] args) {
    ObjectGraph objectGraph = ObjectGraph.create(new UserModule());
    Main m = objectGraph.get(Main.class);
    m.run();
}
}

I managed to inject the "service" field and to call the method "getUserByName("")". But in my "UserService", I have an other custom object ("RepositoryUser" class):

public class UserService implements IUserService {

@Inject
RepositoryUser m_Repository;


@Override
public List<User> getUserByName(String name) {
    return m_Repository.getAll();
}
}

My problem is that this field is not inject: the "m_Repository" field is null and I get a null pointer exception when I try to use my RepositoryUser object.

Here is my Provider:

@Module(
    injects = {UserService.class, Main.class, RepositoryUser.class}
)
 public class UserModule {

@Provides
RepositoryUser provideRepositoryUser() {
    return new RepositoryUser();
}

@Provides
UserService provideUserService() {
    return new UserService();
}
}

Any idea ?

Thanks in advance !

rdroid
  • 43
  • 1
  • 5

1 Answers1

0

It is preferrable to use Constructor Injection in this case. This can be achieved as follows:

Main:

public class Main implements Runnable {

    private final IUserService service;

    @Inject
    public Main(IUserService service) {
        this.service = service;
    }

    @Override
    public void run() {
        for (User f : service.getUserByName("toto")) {
            System.out.print(f.getM_Nom());
        }
    }

    public static void main(String[] args) {
        ObjectGraph objectGraph = ObjectGraph.create(new UserModule());
        Main m = objectGraph.get(Main.class);
        m.run();
    }
}

UserService:

public class UserService implements IUserService {

    private final RepositoryUser m_Repository;

    @Inject
    public UserService(RepositoryUser repository) {
        m_Repository = repository;
    }

    @Override
    public List<User> getUserByName(String name) {
        return m_Repository.getAll();
    }
}

RepositoryUser:

public class RepositoryUser {

    @Inject
    public RepositoryUser() {
    }

    /* ... */
}

UserModule:

@Module(injects = Main.class)
public class UserModule {

    @Provides
    IUserService provideIUserService(UserService userService){
        return userService;
    }
}

Everywhere the @Inject annotation is present on a constructor, Dagger can automatically create an instance of that item. So when you request a RepositoryUser instance in the UserService constructor, Dagger will see the @Inject annotation on RepositoryUser's constructor, and use that to create a new instance. We do not need an @Provides method here.

The IUserService parameter on the Main constructor cannot be instantiated, since it is an interface. Using the provideIUserService method in the module, we tell Dagger that we want it to create a new UserService instance.

We do have an @Inject annotation on the Main constructor, but we request it using ObjectGraph.get(Class<T> clzz). Therefore, we need to add injects = Main.class to our module.

Community
  • 1
  • 1
nhaarman
  • 98,571
  • 55
  • 246
  • 278
  • And what about unit testing and Mock objects ? How can I inject a mock repository to test my Service so ? – rdroid Dec 23 '14 at 15:14
  • Don't use Dagger :). `RepositoryUser repository = mock(RepositoryUser.class); UserService service = new UserService(repository);` – nhaarman Dec 23 '14 at 15:15