Android IOC Dagger Framework - How to inject a nested field ?

为君一笑 提交于 2019-12-11 07:13:23

问题


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 !


回答1:


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.



来源:https://stackoverflow.com/questions/27606149/android-ioc-dagger-framework-how-to-inject-a-nested-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!