Dagger2从两个不同的类中注入依赖关系的最佳方法

时间:2017-12-06 13:26:49

标签: android dependency-injection dagger-2

在搜索并尝试了太多的东西之后,我陷入了一些看似简单的问题。 下面是我的模块,它适用于注入改造。

@Module
public class NetworkingModule
{
    @Provides
    public Retrofit providesRetrofit()
    {
        Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
        Retrofit retrofit = new Retrofit.Builder()
                                        .baseUrl(Constants.BASE_URL)
                                        .addConverterFactory(GsonConverterFactory.create(gson))
                                        .build();

        return retrofit;
    }


}

我的网络组件

@Component( modules = NetworkingModule.class)
public interface NetworkingComponent {
    void inject(DashboardPresenterImpl target);

    void inject(PicksPresenterImpl picksPresenter);

    void inject(LoadsPresenterImpl loadsPresenter);

    void inject(ShippingPresenterImpl shippingPresenter);

    void inject(GeneralFilePresenterImpl generalFilePresenter);
}

带有构造函数注入的实用程序类。请注意,该课程还注册了AppPreferences。

public class AppUtils {
    private Context context;

    @Inject
    AppPreferences preferences;

    @Inject
    public AppUtils(@ActivityContext Context context)
    {
        this.context = context;

        /*ActivityComponent component = DaggerActivityComponent.builder()
                .activityModule(new ActivityModule((Activity) context))
                .build();
        component.inject(this);*/
    }
}

现在我的代码中我想实现这个

Class MyPresenterImpl{
@Inject
    Retrofit retrofit;

    @Inject
    AppUtils appUtils;
}

请建议一种优化和良好的方法来实现上述目标。

修改

添加了AppPreference.java

public class AppPreferences {
    @Inject
    SharedPreferences sharedPreferences;

    private SharedPreferences.Editor editor;

    @Inject
    public AppPreferences(@ActivityContext Context context)
    {
        ApplicationComponent component = DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule((Application) context.getApplicationContext()))
                .build();
        component.inject(this);

        editor = sharedPreferences.edit();
    }

    public void putString(String key, String value)
    {
        editor.putString(key, value).commit();
    }

    public String getString(String key)
    {
        return sharedPreferences.getString(key, null);
    }

}

2 个答案:

答案 0 :(得分:1)

我的建议: 创建上下文模块:

@Module
public class ContextModule
{
    Context context;

    public ContextModule(Context context) {
        this.context = context;
    }

    @Provides
    @AppScope
    Context context() {
        return context;
    }
}

创建SharedPreferences模块

@Module
public class SharedPreferencesModule
{

    @Provides
    @AppScope
    AppSharedPreferences provideAppSharedPreferences(Context context) {
        return new AppSharedPreferences(context.getSharedPreferences("App",Context.MODE_PRIVATE));
    }
}

同样的方法如果需要,您可以创建更多模块(例如,对于AppUtils)

而不是为网络创建单独的组件,为您的应用创建一个

@Component( modules = {ContextModule.class, NetworkingModule.class, SharedPreferencesModule})
public interface AppComponent {...

答案 1 :(得分:1)

请决定是否要使用场注入或构造函数注入,并希望选择构造函数注入

public class AppUtils {
  private Context context;

  @Inject // field injection?
  AppPreferences preferences;

  @Inject // constructor injection?
  public AppUtils(@ActivityContext Context context)
  {
    // ...
  }
}

如果您使用构造函数注入,Dagger将不会注入您的字段,之后您也不应该自己调用它。您的组件应该不包含注入演示者等的所有方法。

如果你需要什么,可以把它放在构造函数中。

public class AppUtils {
  private Context context;
  private AppPreferences preferences;

  @Inject // constructor injection!
  public AppUtils(@ActivityContext Context context, AppPreferences preferences)
  {
    // ...
  }
}

同样适用于MyPresenterImpl。如果你依赖某些东西,把它放在构造函数中,用@Inject标记构造函数,Dagger将为你创建所有依赖项的对象。

您的组件应该只包含适用于Android框架类型的.inject(..)方法(活动,片段,...),而不包含任何其他内容。

我最近还写了一篇关于Dagger使用的some general concepts文章。