2017-02-07 14 views
0

Я пытаюсь сделать инъекцию поля с помощью Dagger2. Я понимаю, что мне нужно вызвать инъекцию вручную в случае инъекции метода. Я в первую очередь пытаюсь ввести двигатель для автомобиля. Двигатель определяется во время выполнения и вводится.Dagger2 Основы - Инъекция поля - Не работает

Данные идет как этот

CarInterface

 import dagger.Binds; 

     public interface Car { 

      public void run(); 
     } 

Реализация автомобилей

public class Volkswagen implements Car { 

@Inject 
public Engine engine; 

public void run() { 
    // TODO Auto-generated method stub 
    System.out.println("About to Run"); 

    engine.start(); 

} 


} 

Интерфейс двигателя

public interface Engine { 

public String start(); 


} 

Реализация двигателя

public class Ferrari4Cylinder implements Engine{ 

@Override 
public String start() { 
    // TODO Auto-generated method stub 
    return "Ignition----Vroom-- Vroom-- Sweet Purring Sound"; 
} 

} 

Модуль автомобиля

public class CarModule{ 

@Provides @Singleton 
Car provideCar(){ 
    return new Volkswagen(); 
} 

} 

Модуль двигателя

@Module 
public class EngineModule { 

@Provides @Singleton 
public Engine provideEngine(){ 
    return new Ferrari4Cylinder(); 
} 
} 

компонентов класса

@Singleton 
@Component(modules = {CarModule.class, EngineModule.class}) 
public interface MyCarComponent { 

public Car provideCar(); 
void inject(Car car); 

} 

Главный метод

public class Main { 

public static void main(String[] args) { 
    // TODO Auto-generated method stub 

    MyCarComponent carComponent= DaggerMyCarComponent.builder().build(); 
    Car car = carComponent.provideCar();  
    carComponent.inject(car); 
    car.run(); 
} 

} 

По какой-то причине: Метод Car.run() всегда возвращает значение null, так как Двигатель никогда не был введен в эксплуатацию. Исключение в теме "main" java.lang.NullPointerException

Может ли кто-нибудь помочь в том, что здесь происходит?

Обновление 9/02/2016: Я выяснил, что следующее изменение компонента для указания фактической реализации работает, как показано ниже. Не знаю, почему другого нет, но это помогло мне продвинуться по этому вопросу.

@Singleton 
@Component(modules = {CarModule.class, EngineModule.class}) 
public interface MyCarComponent { 

public Volkswagen provideCar(); 
void inject(Volkswagen car); 

} 

Надеюсь, что это поможет людям, которые пытаются решить проблемы с полевыми инъекциями в кинжале.

+0

Этот код отлично работает, если интерфейс CAR нет. Я попадаю в ошибку, или я пропускаю нотацию? –

+0

Я все еще не могу понять, почему он не работает. Я сделал фиктивный проект так же, как вы, и полевая инъекция не работает в этом проекте. Я внес изменения, которые вы предложили в последних комментариях, чтобы изменить их на Volkwagen, но все же я не могу успешно запустить проект. Он по-прежнему содержит исключение с помощью исключения из нулевого указателя. –

+0

Вы могли понять это? Если вы можете отправить мне код, который я могу посмотреть? –

ответ

0

Возможно, вы забыли добавить EngineModule в MyCarComponent.

Для ввода в эксплуатацию вы должны добавить аннотацию @Inject на Engine в классе Car. Однако рекомендуется избегать полевой инъекции, если это возможно. Вместо того, чтобы рассмотреть возможность сделать это:

public class Volkswagen implements Car { 

    private final Engine engine; 

    public Volkswagen(Engine engine) { 
    this.engine = engine; 
    } 

} 

Тогда в CarModule

@Provides 
@Singleton 
static Car provideCar(Engine engine) { 
    return new Volkswagen(engine); 
} 

Кроме того, этот способ вам не понадобится inject метод на интерфейсе компонента.

Не забудьте добавить EngineModule к компоненту, чтобы кинжал мог предоставить Engine.

+0

Спасибо, это была опечатка. Я также узнал, что если интерфейс автомобиля отсутствует. Он работает отлично. Обновит мой вопрос. Я ударил ошибку? –

+0

Я не уверен, что вы имеете в виду «Интерфейс автомобиля нет». Вы можете объяснить? – benji

+0

Если я изменю код, чтобы он выглядел, это работает публичный класс Volkswagen { @Inject общественный двигатель двигателя; public void run() { // TODO Автоматически генерируемый метод заглушки System.out.println («О запуске»); engine.start(); } Затем измените класс компонентов, чтобы он выглядел как этот общедоступный Volkwagen provisionCar(); void inject (автомобиль Volkswagen); –

0

Вам необходимо аннотировать ваше поле двигателя с помощью @Inject. Я также считаю, что вам необходимо предоставить реализованный класс (Volkswagen, а не только автомобиль) для вашего метода инъекции.

public class Volkswagen implements Car { 

    @Inject public Engine engine; 

    public void run() { 
    System.out.println("About to Run"); 

    engine.start(); 
    } 
} 

-

@Singleton 
@Component(modules = {CarModule.class, EngineModule.class}) 
public interface MyCarComponent { 

    public Car provideCar(); 
    void inject(Volkswagen car); 

} 
+0

Спасибо, я думаю, что у меня был EngineModule, но пропустил его в вопросе. Добавление Volkswagen в компонент, фактически заставляет его работать. Но это заставляет меня изменить метод обеспечения, чтобы вернуть Volkswagen rathe, чем автомобиль. Это странно, поскольку я думал, что вся идея состоит в том, чтобы перемещаться по графу объектов и определять зависимости. –