¿Es posible a los miembros de @Inject (proporcionados a través de @Provides), que contienen un Contexto de Actividad de la Actividad Base

Bueno. Déjame tratar de romper esta situación, porque creo que es probablemente un poco poco claro en el título. Antes de ir más lejos, voy a decir que, en la medida de lo posible, he intentado basar la estructura básica de esta aplicación de los ejemplos oficiales daga .

Esencialmente lo que estoy tratando de hacer es ser capaz de inyectar un LocationClient en mi SplashActivity , para establecer una conexión (a través de LocationClient.connect() ) tan pronto como se abra la aplicación.

Ahora, obviamente, LocationClient no puede ser inyectado a través de cualquier tipo de constructor por defecto (requiere algunas cosas bastante específicas (un contexto y algunas devoluciones de llamada). Así que he creado un @Provides para ello en mi ActivityModule :

 @Provides @Singleton LocationClient providesLocationClient(@ForApplication Context context, LocationService service) { return new LocationClient(context, service, service); } 

LocationService es la clase que he creado para implementar las devoluciones de llamada requeridas por LocationClient . También estoy proporcionando que a través de un @Provides en mi ActivityModule :

 @Provides @Singleton LocationService providesLocationService(@ForActivity Context context, Logger logger) { return new LocationService(context, logger); } 

Proporcionaré código completo de todos los archivos relevantes al final de esto, como referencia.

Por lo tanto, quiero @Inject un LocationClient en mi SplashActivity . Sin embargo, cuando hago esto, consigo el error siguiente:

 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 

Sólo hay dos maneras que he encontrado para evitar este error, y ni lograr lo que necesito. Yo tambien puedo

  1. Mueva la inyección de LocationClient a un fragmento. Esto no es bueno, porque este punto es demasiado tarde en el flujo de proceso de la aplicación. Quiero ser capaz de empezar a hacer llamadas a la LocationClient en este punto, que requiere una conexión que se han hecho.

  2. Quite la referencia a un Contexto de actividad en @Provides para LocationService y mueva @Provides de ActivityModule a AndroidModule . Esto también no es bueno, ya que necesito el Contexto de actividad para lograr algunas cosas en las devoluciones de llamada (como se ve en los ejemplos de Google para configurar los nuevos servicios de ubicación.

Por lo tanto, ese es el tipo de dilema en el que estoy atrapado. Espero que esto haga alguna apariencia de sentido. Tengo problemas para explicarlo, ya que está tan extendido. A continuación se muestra el código para mi ActivityModule , mi AndroidModule , mi archivo de aplicación y mi 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); } } 

Módulo Android

 @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); } } 

Archivo de la aplicación

 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); } 

Sé que esto es una vieja pregunta pero ¿usted recordó anotar el constructor de LocationService con @Inject ?

También el registrador necesario por LocationService podría ser ambiguo, es posible que necesite un provideLogger también para hacer Dagger capaz de localizar esa dependencia.

Las únicas fuentes posibles del error hasta donde puedo ver.

  • ¿Es posible usar Dagger en el proyecto de la biblioteca?
  • No se puede encontrar la clase de símbolo "Generated" para Dagger 2
  • Dagger v2: Inyectar 2 ámbitos diferentes en un objeto
  • Inyectar base de datos en un ContentProvider con daga
  • Utilice los módulos Dagger sin la directiva "inyecta"
  • Dagger2 dagger.android. * Las clases no existen
  • Daga que no genera componentes para / clase de prueba
  • Ciclo de inclusión del módulo Dagger
  • Dagger2: Error cuando dos componentes tienen la misma firma de método de inyección
  • @Injects después de @Produces?
  • Dagger 2, a veces en la compilación me sale "no se puede encontrar la clase de símbolo DaggerApplicationComponent"
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.