2015-06-08 73 views
1

我試圖在Android應用程序中做一個非常簡單的依賴注入。我使用匕首2作爲DI工具。匕首2 - 無法注入對象

的問題是沒有注入正在發生:

這裏是我的代碼:

//在其所有的敬畏注視Motor.java。

public class Motor { 

    private int rpm; 

    public Motor(){ 
     this.rpm = 10; //default will be 10 
    } 

    public int getRpm(){ 
     return rpm; 
    } 

    public void accelerate(int value){ 
     rpm = rpm + value; 
    } 

    public void brake(){ 
     rpm = 0; 
    } 
} 

這裏是Vehicle.java其中公用事業類電機:

import javax.inject.Inject; 


public class Vehicle { 

    private Motor motor; 

    @Inject 
    public Vehicle(Motor motor){ 
     this.motor = motor; 
    } 

    public void increaseSpeed(int value){ 
     motor.accelerate(value); 
    } 

    public void stop(){ 
     motor.brake(); 
    } 

    public int getSpeed(){ 
     return motor.getRpm(); 
    } 
} 

然後我創建了一個VehicleModule.java類來定義我的供應商:

import javax.inject.Singleton; 

import dagger.Module; 
import dagger.Provides; 



@Module 
public class VehicleModule { 

    @Provides 
    @Singleton 
    Motor provideMotor(){ 
     return new Motor(); 
    } 

    @Provides @Singleton 
    Vehicle provideVehicle(){ 
     return new Vehicle(new Motor()); 
    } 
} 

我的話,我有一個接口組件註釋,定義如下:

import javax.inject.Singleton; 

import Modules.VehicleModule; 
import dagger.Component; 

@Singleton 
@Component(modules = {VehicleModule.class}) 
public interface VehicleComponent { 

    Vehicle provideVehicle(); 

} 

這裏是一個應該被注入我的Android MainActivity類別,但它不是,誰能幫助:

import javax.inject.Inject; 

public class MainActivity extends ActionBarActivity { 

    @Inject 
    Vehicle vehicle; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 


     Toast.makeText(this, String.valueOf(vehicle.getSpeed()), Toast.LENGTH_SHORT).show(); 
    } 
} 

即時得到車輛空指針異常:順便說

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.example.uen229.myapplication.Vehicle.getSpeed()' on a null object reference 

我gradle這個依賴是這樣的:

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    compile 'com.android.support:appcompat-v7:22.2.0' 
    compile 'com.google.dagger:dagger:2.0' 
} 

回答

5

這裏是我的Android MainActivity類別應注入,但它不是

當你用@Inject註釋某些東西時,你會期待神奇的事情發生。雖然神奇的東西發生,它不是神奇。你需要自己做,通過實例化Dagger生成的組件實現。

你可以用幾種方法做到這一點,我將描述兩種。


首先,在你MainActivityonCreate

private Vehicle vehicle; // Note, no @Inject annotation 

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    VehicleComponent vehicleComponent = DaggerVehicleComponent.create(); 
    this.vehicle = vehicleComponent.provideVehicle(); 

    Toast.makeText(this, String.valueOf(vehicle.getSpeed()), Toast.LENGTH_SHORT).show(); 
} 

在這種情況下,你創建的VehicleComponent一個實例,通過實施匕首,並從中獲取Vehicle實例。 vehicle字段未被註釋@Inject。這具有的優勢是該字段可以是private,這是一件好事。


其次,如果你想匕首注入你的領域,你需要一個inject方法添加到您的VehicleComponent

@Singleton 
@Component(modules = {VehicleModule.class}) 
public interface VehicleComponent { 

    Vehicle provideVehicle(); 

    void inject(MainActivity mainActivity); 
} 

在你MainActivity類,你叫inject(this),這將填補vehicle場:

@Inject 
Vehicle vehicle; // Note, package-local 

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    VehicleComponent vehicleComponent = DaggerVehicleComponent.create(); 
    vehicleComponent.inject(this); 

    Toast.makeText(this, String.valueOf(vehicle.getSpeed()), Toast.LENGTH_SHORT).show(); 
} 

這帶來了一些額外的配置,但有時是neces薩利。 但我喜歡第一種方法。


作爲最後的評論,讓我們看看你的VehicleModule,並真的使用匕首的力量。

除了使用模塊自己創建實例外,還可以爲你製作Dagger。你已經用@Inject註解了Vehicle構造函數,所以Dagger會知道使用這個構造函數。但是,它需要一個Motor的實例,它不知道。如果您還向Motor的構造函數添加了@Inject註釋,並且使用@Singleton註釋了Motor類,那麼您完全可以擺脫VehicleModule

例如:

@Singleton 
public class Motor { 

    private int rpm; 

    @Inject // Just an annotation to let Dagger know how to retrieve an instance of Motor. 
    public Motor(){ 
     this.rpm = 10; //default will be 10 
    } 

    public int getRpm(){ 
     return rpm; 
    } 

    public void accelerate(int value){ 
     rpm = rpm + value; 
    } 

    public void brake(){ 
     rpm = 0; 
    } 
} 

Vehicle類:

@Singleton 
public class Vehicle { 

    private Motor motor; 

    @Inject 
    public Vehicle(Motor motor){ 
     this.motor = motor; 
    } 

    public void increaseSpeed(int value){ 
     motor.accelerate(value); 
    } 

    public void stop(){ 
     motor.brake(); 
    } 

    public int getSpeed(){ 
     return motor.getRpm(); 
    } 
} 

現在可以安全地刪除VehicleModule類,並刪除您VehicleComponent的引用。

+0

它說它不能在IDE中找到DaggerVehicleComponent。有任何想法嗎 ?我刪除了注入註解,並遵循你的第一個方法,所以我可以製作私有方法。它的包裹在當地。現在每個地方都包裝在當地。但它沒有找到DaggerVehicleComponent。我猜這是自動生成的東西。 – j2emanue

+0

查看我的答案[這裏](http://stackoverflow.com/a/29707308/675383),瞭解如何讓Android Studio找到生成的類。 – nhaarman

+1

使用此應用插件:'com.neenbedankt.android-apt',並在build.gradle文件中:classpath'com.neenbedankt.gradle.plugins:android-apt:1.4'讓它爲我自動生成類。你的解釋非常好。謝謝你,先生。 – j2emanue

0

你缺少以下步驟

你在應用程序類

public class D2EApplication extends Applicaiton { 
    public static D2EComponent component(Context context) { 
      return ((D2EBaseApplication) context.getApplicationContext()).component; 
     } 

     public final static class DaggerComponentInitializer { 

      public static D2EComponent init(D2EBaseApplication app) { 
       return DaggerD2EComponent.builder() 
         .systemServicesModule(new VehicleModule(app)) 
         .build(); 
      } 

     } 
    } 

創建這樣的模塊,並將其注入到活動

D2EApplication.component(this).inject(this);