Ok. Lasciatemi provare a rompere questa situazione, perché penso che sia probabilmente un po 'poco chiaro dal titolo. Prima di proseguire, dirò che per quanto possibile, ho cercato di basare la struttura di base di questa app su official dagger examples.E 'possibile i membri @Inject (forniti tramite @Provides), contenenti un contesto di attività dall'attività di base
Essenzialmente quello che sto cercando di fare è essere in grado di iniettare un LocationClient nel mio SplashActivity
, in modo da stabilire un collegamento (tramite LocationClient.connect()
) non appena si apre l'App. .
Ora, ovviamente, LocationClient non può essere iniettato attraverso qualsiasi tipo di costruttore di default (che richiede alcune cose piuttosto specifici (un contesto, e alcuni callback) Così, ho creato un @Provides
per esso nella mia ActivityModule
:
@Provides
@Singleton
LocationClient providesLocationClient(@ForApplication Context context, LocationService service) {
return new LocationClient(context, service, service);
}
LocationService
è la classe che ho creato per implementare i callback richieste dalla LocationClient
sto anche a condizione che attraverso un @Provides
nel mio ActivityModule
:.
@Provides
@Singleton
LocationService providesLocationService(@ForActivity Context context, Logger logger) {
return new LocationService(context, logger);
}
Fornirò il codice completo di tutti i file rilevanti alla fine di questo, per riferimento.
Quindi, voglio @Inject
a LocationClient
sul mio SplashActivity
. Tuttavia, quando faccio questo, ottengo il seguente errore:
No injectable members on com.google.android.gms.location.LocationClient. Do you want to add an injectable constructor? required by class m.myapp.android.storemode.presentation.activity.SplashActivity
Ci sono solo due modi che ho trovato per evitare questo errore, e non compiere ciò che mi serve. Posso sia
Spostare l'iniezione di
LocationClient
su un frammento. Questo non va bene, perché questo punto è troppo tardi nel flusso di processo dell'applicazione. Voglio essere in grado di iniziare a effettuare chiamate alloLocationClient
da questo punto, che richiede che sia stata effettuata una connessione.Rimuovere il riferimento ad un contesto di attività nel
@Provides
perLocationService
, e spostare il@Provides
ActivityModule
-AndroidModule
. Questo è anche non va bene, perché ho bisogno del contesto di attività per realizzare alcune cose nelle callback (come si è visto negli esempi di Google per la creazione di nuovi servizi di localizzazione.
Quindi, questo è il tipo di dilemma Sono bloccato in. Spero che questo abbia qualche parvenza di senso, ho difficoltà a spiegarlo, dato che è molto diffuso.Di seguito è riportato il codice per il mio ActivityModule
, la mia AndroidModule
, il mio file di applicazione, e la mia BaseActivity
:
ActivityModule
@Module(
injects = {MainActivity.class,
SplashActivity.class,
HomeFragment.class,
StoreLocatorFragment.class,
BrowseProductsFragment.class,
BrowseProductCategoriesFragment.class},
includes = {NetworkImageModule.class, ApiModule.class, WatchListModule.class},
complete = false
)
public class ActivityModule {
private final BaseActivity mActivity;
public ActivityModule(BaseActivity activity) {
this.mActivity = activity;
}
/**
* Allow the mActivity context to be injected but require that it be annotated with {@link
* ForActivity @ForActivity} to explicitly differentiate it from application context.
*/
@Provides
@Singleton
@ForActivity
Context provideActivityContext() {
return mActivity;
}
@Provides
@Singleton
KeyboardHider provideKeyboardHider(InputMethodManager imm) {
return new KeyboardHider(imm);
}
@Provides
ProgressDialog providesProgressDialog() {
return new ProgressDialog(mActivity);
}
@Provides
@Singleton
LocationService providesLocationService(@ForActivity Context context, Logger logger) {
return new LocationService(context, logger);
}
@Provides
@Singleton
LocationClient providesLocationClient(@ForApplication Context context, LocationService service) {
return new LocationClient(context, service, service);
}
@Provides
@Singleton
PIVenueIdService providesPiVenueIdService(LocationClient locationClient) {
return new PIVenueIdService(locationClient);
}
}
Android modulo
@Module(library = true)
public class AndroidModule {
/**
* SharedPreferences name
*/
public static final String PREFERENCE_NAME = AndroidModule.class
.getPackage()
.getName() +
"Preferences";
private final StoreModeApplication mApplication;
//Only created for testing
public AndroidModule() {
mApplication = null;
}
public AndroidModule(StoreModeApplication application) {
mApplication = checkNotNull(application);
}
/**
* Allow the application context to be injected but require that it be annotated with {@link
* ForApplication @Annotation} to explicitly differentiate it from an activity context.
*/
@Provides
@Singleton
@ForApplication
Context provideApplicationContext() {
return mApplication;
}
@Provides
@Singleton
SharedPreferences provideSharedPreferences() {
return mApplication.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
}
@Provides
@Singleton
RequestQueue provideRequestQueue() {
return Volley.newRequestQueue(mApplication);
}
@Provides
@Singleton
ActivityManager provideActivityManager() {
return (ActivityManager) mApplication.getSystemService(Context.ACTIVITY_SERVICE);
}
@Provides
@Singleton
LocationManager provideLocationManager() {
return (LocationManager) mApplication.getSystemService(Context.LOCATION_SERVICE);
}
@Provides
@Singleton
Logger provideLoggingService() {
return new LogCatLogger();
}
@Provides
@Singleton
Gson provideGson() {
return new Gson();
}
@Provides
@Singleton
InputMethodManager provideInputMethodManager() {
return (InputMethodManager) mApplication.getSystemService(Context.INPUT_METHOD_SERVICE);
}
}
File di applicazione
public class StoreModeApplication extends Application {
private static StoreModeApplication sInstance;
private ObjectGraph mGraph;
/**
* Only use this for easy access to inject function
*/
public static StoreModeApplication getInstance() {
return sInstance;
}
@Override
public void onCreate() {
super.onCreate();
// Setup debugging for butterknife
Views.setDebug(BuildConfig.DEBUG);
// Create ability to get instance
sInstance = this;
// Setup DI
mGraph = ObjectGraph.create(getModules().toArray());
}
/**
* Used for injecting dependencies
*
* @param object object that needs dependencies injected
*/
public void inject(Object object) {
mGraph.inject(object);
}
/**
* Gets mGraph.
*
* @return Value of mGraph.
*/
public ObjectGraph getApplicationGraph() {
return mGraph;
}
/**
* Creates a list containing all the modules required for dagger
*/
private List<Object> getModules() {
return Arrays.asList(
new AndroidModule(this),
new ActivityObjectMapperModule(),
new NetworkImageModule()
);
}
BaseActivity
public abstract class BaseActivity extends Activity {
private ObjectGraph mActivityGraph;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StoreModeApplication storeModeApplication = StoreModeApplication.getInstance();
mActivityGraph = storeModeApplication.getApplicationGraph()
.plus(
getModules().toArray()
);
mActivityGraph.inject(this);
}
@Override
protected void onDestroy() {
// Eagerly clear the reference to the activity graph to allow it to be garbage collected as
// soon as possible.
mActivityGraph = null;
super.onDestroy();
}
protected List<Object> getModules() {
return Arrays.asList(
new ActivityModule(this),
new StoreLocatorFragmentModule(),
new WatchListModule()
);
}
/**
* Inject the supplied {@code object} using the activity-specific graph.
*/
public void inject(Object object) {
mActivityGraph.inject(object);
}
Ho una situazione simile. Io uso una classe LocationService che utilizza un LocationClient creato usando una factory e io inserisco il LocationService nell'attività; il LocationService è anche legato al ciclo di vita delle attività, quindi avvia/arresta gli aggiornamenti di posizione in onResume e onPause. Io uso un bus eventi (Otto) per inviare un LocationChangedEvent. Posso fornire un codice, anche se non sono sicuro che sia l'approccio giusto al tuo problema. – alex
Lo hai mai capito? Sto avendo un problema simile. –