Dagger2 Optimal way to inject dependencies from two different classes

和自甴很熟 提交于 2019-12-13 02:55:11

问题


After searching and trying too many things i'm stuck in some what seems like an easy problem. Below is my module which is reponsible for injecting retrofit.

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


}

My NetworkComponent

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

A utility class with constructor injection. Please note this class also has injection of 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);*/
    }
}

Now in my Code i want to achieve this

Class MyPresenterImpl{
@Inject
    Retrofit retrofit;

    @Inject
    AppUtils appUtils;
}

Please suggest an optimize and good way to achieve the above.

EDIT

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

}

回答1:


Please decide on whether you want to use field injection or constructor injection, and hopefully choose constructor injection.

public class AppUtils {
  private Context context;

  @Inject // field injection?
  AppPreferences preferences;

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

Dagger won't inject your fields if you use constructor injection and you should not call it yourself afterwards either. Your component should really not contain all those methods to inject your presenter etc.

If you need something, put it in the constructor.

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

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

The same applies for MyPresenterImpl. If you depend on something, put it in the constructor, mark the constructor with @Inject, and Dagger will create the object for you with all the dependencies provided.

Your components should only contain .inject(..) method for Android framework types (Activities, Fragments, ...) and nothing else.

I also wrote an article recently with some general concepts about the use of Dagger.




回答2:


my suggestion: create context module:

@Module
public class ContextModule
{
    Context context;

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

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

create SharedPreferences module

@Module
public class SharedPreferencesModule
{

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

same way You can create more modules if you need to (for example for AppUtils)

instead of creating separate component for network, create one for your app

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


来源:https://stackoverflow.com/questions/47675483/dagger2-optimal-way-to-inject-dependencies-from-two-different-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!