是否可以@Inject成员(通过@Provides提供),包含来自Base Activity的Activity Context

时间:2013-09-10 21:48:47

标签: android dagger

好。让我试着打破这种情况,因为我认为从标题中可能有点不清楚。在进一步讨论之前,我会尽可能地说,我已经尝试将此应用程序的基本结构基于official dagger examples

基本上我要做的是能够将LocationClient注入我的SplashActivity,以便在应用程序出现时立即建立连接(通过LocationClient.connect())打开。

现在,显然,LocationClient不能通过任何类型的默认构造函数进行注入(它需要一些非常具体的东西(一个上下文和一些回调)。所以,我已经为它创建了一个@Provides我的ActivityModule

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

LocationService是我为实现LocationClient所需的回调而创建的类。我也是通过@Provides中的ActivityModule提供的:

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

我将在此末尾提供所有相关文件的完整代码,供参考。

所以,我希望@Inject LocationClient加入我的SplashActivity。但是,当我这样做时,我收到以下错误:

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

我发现只有两种方法可以避免这种错误,而且也没有达到我的需要。我可以

  1. LocationClient的注入移动到片段上。这并不好,因为这一点对于应用程序的流程来说已经太晚了。我希望能够在此时开始调用LocationClient,这需要建立连接。

  2. 删除@Provides LocationService中对活动上下文的引用,并将@ProvidesActivityModule移至AndroidModule。这也没有用,因为我需要活动上下文来完成回调中的一些事情(如Google示例中所示,用于设置新的位置服务。

  3. 所以,这就是我陷入困境的困境。我希望这会产生一些相似之处。我无法解释它,因为它如此分散。以下是我的ActivityModule,我的AndroidModule,我的应用程序文件和我的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模块

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

    申请文件

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

1 个答案:

答案 0 :(得分:0)

我知道这是一个老问题,但您是否记得用@Inject注释LocationService的构造函数?

此外,LocationService所需的Logger可能不明确,您可能还需要provideLogger才能让Dagger找到该依赖项。

据我所知,唯一可能的错误来源。