2015-10-12 14 views
5

Ricevo sempre un'eccezione di puntatore nullo quando provo a inserire l'interfaccia nella classe di implementazione. qui è il mio codice:Daga 2 - Interfaccia di iniezione nella classe di implementazione - "Tentativo di richiamare il metodo di interfaccia su un riferimento a oggetto nullo"

Ottenere:

Nullpointer errore nel LoginManagerImpl classe alla linea:
@Override
public String getLoginResponse (richiesta String) {
ritorno networkManager.getLoginResponse (richiesta) ;
}

qui NetworkManager è sempre nullo, ti invitiamo a esaminare il codice.

Qui di seguito è il mio codice sorgente:

public class LoginActivity extends Activity { 

    @Inject 
    NetworkManager networkManager; 

    @Inject 
    LoginManager loginManager; 

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

     loginManager.getLoginResponse("valid Login Request"); 
    } 
} 

public interface NetworkManager 
{ 
    String getLoginResponse(String request); 
    String getUserDetailResponse(String request); 
    String getABCResponse(String request); 
} 

public interface LoginManager 
{ 
    String getLoginResponse(String request); 
} 

public class LoginManagerImpl implements LoginManager { 
    @Inject 
    NetworkManager networkManager; 

    public LoginManagerImpl(Context context) 
    { 

    } 

    @Override 
    public String getLoginResponse(String request) { 
     return networkManager.getLoginResponse(request); 
    } 
} 

public class NetworkManagerImpl implements NetworkManager { 

    public NetworkManagerImpl(Context context) 
    { 

    } 
    @Override 
    public String getLoginResponse(String request) { 
     return "valid login response fetched from server"; 
    } 

    @Override 
    public String getUserDetailResponse(String request) { 
     return "valid user deails"; 
    } 

    @Override 
    public String getABCResponse(String request) { 
     return "valid ABC request response"; 
    } 
} 

@Module 
public class AppModule { 

    DaggerApplication application; 

    public AppModule(DaggerApplication application) { 
     this.application = application; 
    } 

    @Provides 
    @Singleton 
    DaggerApplication provideDaggerApplication() { 
     return application; 
    } 

    @Provides 
    @Singleton 
    public Context provideApplicationContext() 
    { 
     return application.getApplicationContext(); 
    } 

    @Provides 
    @Singleton 
    public LoginManager providesLoginManager(Context context) 
    { 
     return new LoginManagerImpl(); 
    } 

    @Provides 
    @Singleton 
    public LoyaltyCardManager providesLoyaltyCardManager(Context context) 
    { 
     return new LoyaltyCardManagerImpl(context); 
    } 

    @Provides 
    @Singleton 
    public NetworkManager providesNetworkManager(Context context) 
    { 
     return new NetworkManagerImpl(context); 
    } 
} 

@Singleton 
@Component(
     modules = { 
       com.dagger.component.AppModule.class 
     }) 
public interface ApplicationComponent { 
    void inject (LoginActivity activity); 

    NetworkManager getNetworkManager(); 
    LoginManager getLoginManager(); 
} 

risposta

4

Ci sono due modi per farvi Dagger iniettare le dipendenze come il campo networkManager in LoginManagerImpl.

  1. Annotare il suo costruttore con @Inject e cambiare providesLoginManager(Context) a

    @Provides @Singleton 
    LoginManager providesLoginManager(LoginManagerImpl manager) { 
        return manager; 
    } 
    

    che significherà Dagger fornirà la LoginManagerImpl, e il metodo di @Provides si lega a quella LoginManager.

  2. Se si desidera creare un'istanza LoginManagerImpl se stessi in providesLoginManager(Context), quindi richiedere anche una MembersInjector<LoginManagerImpl> e utilizzarlo per iniettare i campi come networkManager:

    @Provides @Singleton 
    LoginManager providesLoginManager(Context context, MembersInjector<LoginManagerImpl> membersInjector) { 
        LoginManagerImpl manager = new LoginManagerImpl(context); 
        membersInjector.injectMembers(manager); 
        return manager; 
    } 
    

Per esempio, io consiglierei di opzione # 1 . L'utilizzo di MembersInjector è davvero utile per le classi che non puoi consentire a Dagger di creare un'istanza, ad esempio Attività Android.

0

L'iniezione di campo non è automatica. È necessario fornire tali dipendenze tramite il costruttore oppure è necessario avviare manualmente l'iniezione di campo nel costruttore.

public class LoginActivity extends Activity {  
    @Inject 
    NetworkManager networkManager; 

    @Inject 
    LoginManager loginManager; 

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

     loginManager.getLoginResponse("valid Login Request"); 
    } 
} 

public interface NetworkManager 
{ 
    String getLoginResponse(String request); 
    String getUserDetailResponse(String request); 
    String getABCResponse(String request); 
} 

public interface LoginManager 
{ 
    String getLoginResponse(String request); 
} 

public class LoginManagerImpl implements LoginManager { 
    @Inject 
    NetworkManager networkManager; 

    public LoginManagerImpl(Context context) {  

     ((DaggerApplication)context).getApplicationComponent().inject(this); 
    } 

    @Override 
    public String getLoginResponse(String request) { 
     return networkManager.getLoginResponse(request); 
    } 
} 

public class NetworkManagerImpl implements NetworkManager { 

    public NetworkManagerImpl(Context context) 
    { 
     ((DaggerApplication)context).getApplicationComponent().inject(this);  } 
    @Override 
    public String getLoginResponse(String request) { 
     return "valid login response fetched from server"; 
    } 

    @Override 
    public String getUserDetailResponse(String request) { 
     return "valid user deails"; 
    } 

    @Override 
    public String getABCResponse(String request) { 
     return "valid ABC request response"; 
    } 
} 

@Module 
public class AppModule { 

    DaggerApplication application; 

    public AppModule(DaggerApplication application) { 
     this.application = application; 
    } 

    @Provides 
    @Singleton 
    DaggerApplication provideDaggerApplication() { 
     return application; 
    } 

    @Provides 
    @Singleton 
    public Context provideApplicationContext() 
    { 
     return application.getApplicationContext(); 
    } 

    @Provides 
    @Singleton 
    public LoginManager providesLoginManager(Context context) 
    { 
     return new LoginManagerImpl(); 
    } 

    @Provides 
    @Singleton 
    public LoyaltyCardManager providesLoyaltyCardManager(Context context) 
    { 
     return new LoyaltyCardManagerImpl(context); 
    } 

    @Provides 
    @Singleton 
    public NetworkManager providesNetworkManager(Context context) 
    { 
     return new NetworkManagerImpl(context); 
    } 
} 

@Singleton 
@Component(
     modules = { 
       com.dagger.component.AppModule.class 
     }) 
public interface ApplicationComponent { 
    void inject(LoginManagerImpl loginManagerImpl); 
    void inject(NetworkManagerImpl networkManagerImpl); 
    void inject (LoginActivity activity); 

    NetworkManager getNetworkManager(); 
    LoginManager getLoginManager(); 
} 

o si deve fornire loro sulla lista degli argomenti del costruttore

@Provides 
    @Singleton 
    public LoginManager providesLoginManager(Context context, NetworkManager networkManager) 
    { 
     return new LoginManagerImpl(context, networkManager); 
    } 
0

ero in grado di risolvere il problema con l'aggiunta di android:name="my_application_class_name" al tag applicazione nel file di AndroidManifest.

Problemi correlati