2015-05-29 13 views
5

Ho appena iniziato a utilizzare Dagger 2 oggi e sono un po 'confuso su come esattamente ho bisogno di impostare tutto.Android Dagger 2 Campo POJO Inietti null

Sto cercando di iniettare un POJO, ma è sempre nullo. In primo luogo, un po 'di codice:

App.java

private AppComponent appComponent; 

@Override 
public void onCreate() { 
    super.onCreate(); 
    appComponent = DaggerAppComponent 
      .builder() 
      .appModule(new AppModule(this)) 
      .build(); 
} 

public AppComponent component() { 
    return appComponent; 
} 

AppModule.java

@Module 
public class AppModule { 
    private Application app; 

    public AppModule(Application app) { 
     this.app = app; 
    } 

    @Provides @Singleton 
    public Application application() { 
     return app; 
    } 
} 

AppComponent.java

@Singleton 
@Component(modules = AppModule.class) 
public interface AppComponent { 
    void inject(App application); 
    Application application(); 
} 

NetworkingManager.java

@Singleton 
public class NetworkingManager { 
    private Context ctx; 

    @Inject 
    public NetworkingManager(Context context) { 
     this.ctx = context; 
    } 
} 

NetModule.java

@Module 
public class NetModule { 
    @Provides @Singleton 
    public NetworkingManager provideNetworkingManager(Application application) { 
     return new NetworkingManager(application); 
    } 
} 

NetComponent.java

@Singleton 
@Component(modules = {NetModule.class}, 
     dependencies = {AppModule.class}) 
public interface NetComponent { 
    void inject(NetworkingManager networkingManager); 
} 

SomeClass.java

@Inject 
NetworkingManager networkingManager; 

public void doSomethingWithNetworkManager() { 
    networkManager.doStuff(); 
} 

Ho passato un bel po 'di tempo guardando attraverso un sacco di tutorial SO, domande ed esempi, ma non sono stato in grado di capire cosa sto facendo male.

Sono sicuro al 99% che ho qualcosa di sbagliato, ma non sono stato in grado di capire cosa.

+0

Sembra che tu abbia un po 'di confusione. Qual è il tuo obiettivo? Dove stai cercando di usare 'NetworkingManager'? – Emmanuel

+0

NetworkManager è attualmente un singleton. Gestisce tutte le reti asincrone. È usato dappertutto. Il mio obiettivo è eliminare il singleton e passare a DI, oltre a rendere la classe testabile. –

risposta

10

In base al tuo commento, si desidera rendere disponibile NetworkingManager in qualsiasi punto dell'applicazione. inizio

Let con la definizione del Component:

@Singleton 
@Component(modules = AppModule.class) 
public interface AppComponent { 
    void inject(App application); 
} 

Questo dice Dagger che questa componente sarà iniettando la classe App. Ora qui puoi anche dire a Dagger altre classi che vorresti iniettare. Quindi, se volete iniettare anche un Activity ad esempio si dovrebbe aggiungere:

@Singleton 
@Component(modules = AppModule.class) 
public interface AppComponent { 
    void inject(App application); 
    void inject(MainActivity activity) //Where MainActivity is a class that extends Activity. 
} 

Si prega di notare che questo non è il modo migliore, IMO, per condividere ampie dipendenze delle applicazioni; dovresti creare un Component che erediti da AppComponent e rendere AppComponent esporre le dipendenze condivise desiderate.

Ora diamo un'occhiata al vostro modulo di classe:

@Module 
public class NetModule { 
    @Provides @Singleton 
    public NetworkingManager provideNetworkingManager(Application application) { 
     return new NetworkingManager(application); 
    } 
} 

Qui siete @Provide ing un NetworkingManager, che va bene. Il tuo NetworkingManager richiede un Application (uno Context), perché non fornire App all'interno di NetworkingManager?O, ancora meglio perché non fornire NetworkingManager all'interno delle AppModule dal AppModule dovrebbe @Provide cose che sono comuni per tutta la Application:

@Module 
public class AppModule { 
    private Application app; 

    public AppModule(Application app) { 
     this.app = app; 
    } 

    @Provides @Singleton 
    public Application application() { 
     return app; 
    } 

    @Provides @Singleton 
    public NetworkingManager provideNetworkingManager(Application application) { 
     return new NetworkingManager(application); 
    } 
} 

Ora all'interno del vostro App classe:

public class App extends Application { 
    private AppComponent appComponent; 

@Override 
public void onCreate() { 
    super.onCreate(); 
    appComponent = DaggerAppComponent 
      .builder() 
      .appModule(new AppModule(this)) 
      .build(); 
    appComponent.inject(this); 
} 

public AppComponent component() { 
    return appComponent; 
} 
} 

E nella nostra ipotetica MainActivity:

public class MainActivity extends Activity { 

private AppComponent appComponent; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    appComponent = ((App)getApplicationContext()).getAppComponent(); 
    appComponent.inject(this); 
    } 
} 

Sembra che non si sta utilizzando @Component(dependencies = {...}) correttamente. dependencies viene utilizzato quando si desidera esporre una dipendenza da uno Component a un altro utilizzando il meccanismo sopra menzionato.

+0

Ok, questo ha un po 'più senso. 1) Presumo in 'App.onCreate()' intendevi '.build()' e non '.inject (this)', poiché 'inject()' restituisce void. 2) 'NetworkingManager' si trova in un pacchetto diverso da' App'. Stavo pensando che sarebbe stato meglio tenere moduli separati per ogni pacchetto. Non è possibile? 3) Ottenere 'AppComponent' in' MainActivity.onCreate() 'va bene per attività e frammenti. Che dire dei POJO che non hanno accesso al contesto dell'applicazione? Devo prima ottenere il contesto in un'attività e passarlo al POJO? Sembra indietro al punto di DI con Dagger. –

+0

1) Hai ragione, ho corretto il codice 'App'. Chiameresti 'inject()' se vuoi anche iniettare 'App'. 2) Puoi sicuramente avere diversi moduli per pacchetto, ma penso che abbia più senso avere moduli diversi per ambito (livello applicazione, livello attività, ecc.). 3) Per i POJO puoi semplicemente annotare il loro costruttore con '@ Inject' se sono usati da una classe che è stata già iniettata da un' Component'. Questo può essere fonte di confusione da cogliere. Possiamo parlarne di più se vuoi in una chat room. – Emmanuel

Problemi correlati