I'm studying the Dagger 2 library and faced a problem of passing parameters which could not be obtained from "extends Application" class.
For example, I need to pass FragmentManager to ViewPager adapter constructor. How would you do that?
MyApplication:
public class MyApplication extends Application {
private MyAppComponent mMyAppComponent;
#Override
public void onCreate() {
super.onCreate();
Context context = getApplicationContext();
mMyAppComponent= DaggerMyAppComponent.builder()
.utilityModule(new UtilityModule())
.locationModule(new LocationModule(context))
.appModule(new AppModule(context))
.pagerAdapterModule(new PagerAdapterModule(context)) //this one is problematic
.build();
}
public MyAppComponent getmMyAppComponent() {
return mMyAppComponent;
}
}
MyAppComponent:
#Singleton
#Component(
modules = {
UtilityModule.class,
LocationModule.class,
PagerAdapterModule.class,
AppModule.class
}
)
public interface MyComponent {
FragmentManager fragmentManager(); //is it right?
public void inject(NavigationActivity navigationActivity);
}
AppModule:
#Module
public class AppModule {
Context context;
public AppModule(Context context) {
this.context = context;
}
#Provides
#Singleton
Context provideApplicationContext() {
return context;
}
}
PagerAdapterModule:
#Module
public class PagerAdapterModule {
Context context;
public PagerAdapterModule(Context context) {
this.context = context;
}
#Provides
#Singleton TabsPagerAdapter provideTabsPagerAdapter(FragmentManager fragmentManager) {
return new TabsPagerAdapter(context, fragmentManager);
}
}
NavigationActivity:
#Inject TabsPagerAdapter mTabsAdapter; //I want this to be initialized
You need to have a FragmentActivity to get a FragmentManager, which means you cannot accomplish it in Application level, because it's too soon. So you have to create a component dependency from AppComponent, let's name it ActivityComponent, which will see all dependencies that AppComponent provides.
#Component(modules = ActivityModule.class, dependencies = MyAppComponent.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
#Module
public class ActivityModule {
FragmentActivity activity;
public ActivityModule(FragmentActivity activity) {
this.activity = activity;
}
#Provides
TabsPagerAdapter provideTabsPagerAdapter() {
return new TabsPagerAdapter(activity, activity.getSupportFragmentManager());
}
}
Now in onCreate() of your activity:
public class MainActivity extends AppCompatActivity {
#Inject
TabsPagerAdapter tabsPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityComponent activityComponent = DaggerActivityComponent.builder()
.activityModule(new ActivityModule(this))
.myAppComponent(MyApplication.getMyAppComponent())
.build();
activityComponent.inject(this);
}
}
i have this constructor for viewPagerAdapter and fragment that injected
#Inject
DashboardFragment dashboardFragment;
#Inject
public HomeViewPageAdapter(FragmentManager fragmentManager) {
super(fragmentManager , BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
MyApplication.component.inject(this);
}
and create this module
#Module
public class HomeActivityModule {
#Provides
HomeViewPageAdapter provideHomeViewPageAdapter(HomeActivity homeActivity) {
return new HomeViewPageAdapter(homeActivity.getSupportFragmentManager());
}
}
and provide HomeActivity
#Module
public class HomeActivityModule {
#Provides
HomeViewPageAdapter provideHomeViewPageAdapter(HomeActivity homeActivity) {
return new HomeViewPageAdapter(homeActivity.getSupportFragmentManager());
}
}
finally in HomeActivity can inject viewPagerAdapter like this
#Inject
HomeViewPageAdapter homeViewPageAdapter;
You can pass the FragmentManager to the PagerAdapterModule:
Context context;
FragmentManager fragmentManager;
public PagerAdapterModule(Context context, FragmentManager fragmentManager) {
this.context = context;
this.fragmentManager = fragmentManager;
}
Related
I was following some examples to work on dagger2. Here I was using dependencies on HomeFragmentComponent to provide reference of context from another scope but its not working.
ContextModule
#Module
public class ContextModule {
private final Context context;
public ContextModule(Context context) {
this.context = context;
}
#Provides
#ShikshyaScope
public Context context(){
return context;
}
}
Network Module :
#Module(includes = ContextModule.class)
public class NetworkModule {
#Provides
#ShikshyaScope
public File file(Context context){
File cacheFile = new File(context.getCacheDir(),"okhttp_cache");
cacheFile.mkdirs();
return cacheFile;
}
ShikshyaApplicationComponent:
#ShikshyaScope
#Component(modules = {NetworkModule.class, PicassoModule.class, StorageModule.class})
public interface ShikshyaApplicationComponent {
void injectShikshyaApplication(ShikshyaBusApplication shikshyaBusApplication);
}
Home Fragment Module :
#Module
public class HomeFragmentModule {
public final HomeFragment homeFragment;
public HomeFragmentModule(HomeFragment homeFragment) {
this.homeFragment = homeFragment;
}
#Provides
#HomeFragmentScope
public HomeFragment homeFragment(){
return homeFragment;
}
#Provides
#HomeFragmentScope
public HomeFragmentView homeFragmentView(HomeFragment homeFragment){
return (HomeFragmentView)homeFragment;
}
#Provides
#HomeFragmentScope
public HomeFragmentPresenter homeFragmentPresenter(HomeFragmentView homeFragmentView,MetaDatabaseRepo metaDatabaseRepo){
return new HomeFragmentPresenter(homeFragmentView,metaDatabaseRepo);
}
#Provides
#HomeFragmentScope
public DatabaseHelper databaseHelper(Context context){
return OpenHelperManager.getHelper(context,DatabaseHelper.class);
}
}
HomeFragmentComponent :
#HomeFragmentScope
#Component(modules = HomeFragmentModule.class,dependencies =ShikshyaApplicationComponent.class)
public interface HomeFragmentComponent {
void injectHomeFragment(HomeFragment homeFragment);
}
Now I get error as
error: android.content.Context cannot be provided without an #Provides-annotated method.
android.content.Context is injected at com.bihani.shikshyabus.di.module.HomeFragmentModule.databaseHelper(context)
com.bihani.shikshyabus.database.DatabaseHelper is injected at
You should include ContextModule as HomeFragmentModule dependency so Dagger2 be able to provide context to DatabaseHelper
#Module(includes = ContextModule.class)
public class HomeFragmentModule {
// Your stuff here
}
I am using the following google sample project: https://github.com/googlesamples/android-architecture-components as a reference for my new project and having difficulties trying to add a second activity to the project.
Here is the error I get when compiling
Error:(22, 8) error: [dagger.android.AndroidInjector.inject(T)] com.apps.myapp.ui.common.MainActivity cannot be provided without an #Inject constructor or from an #Provides-annotated method. This type supports members injection but cannot be implicitly provided.
com.apps.myapp.ui.common.MainActivity is injected at
com.apps.myapp.ui.common.NavigationController.<init>(mainActivity)
com.apps.myapp.ui.common.NavigationController is injected at
com.apps.myapp.ui.addContacts.AddContactsFragment.navigationController
com.apps.myapp.ui.addContacts.AddContactsFragment is injected at
dagger.android.AndroidInjector.inject(arg0)
A binding with matching key exists in component: com.apps.myapp.di.ActivityModule_ContributeMainActivity.MainActivitySubcomponent
Here is my code
ActivityModule
#Module
public abstract class ActivityModule {
#ContributesAndroidInjector(modules = FragmentBuildersModule.class)
abstract MainActivity contributeMainActivity();
#ContributesAndroidInjector(modules = FragmentBuildersModule.class)
abstract ContactActivity contributeContactActivity();
}
AppComponent
#Singleton
#Component(modules = {
AndroidInjectionModule.class,
AppModule.class,
ActivityModule.class})
public interface AppComponent {
#Component.Builder
interface Builder {
#BindsInstance Builder application(Application application);
AppComponent build();
}
void inject(App app);
}
AppInjector
public class AppInjector {
private AppInjector() {}
public static void init(App app) {DaggerAppComponent.builder().application(app).build().inject(app);
app.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
handleActivity(activity);
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
});
}
private static void handleActivity(Activity activity) {
if (activity instanceof HasSupportFragmentInjector) {
AndroidInjection.inject(activity);
}
if (activity instanceof FragmentActivity) {
((FragmentActivity) activity).getSupportFragmentManager()
.registerFragmentLifecycleCallbacks(
new FragmentManager.FragmentLifecycleCallbacks() {
#Override
public void onFragmentCreated(FragmentManager fm, Fragment f,
Bundle savedInstanceState) {
if (f instanceof Injectable) {
AndroidSupportInjection.inject(f);
}
}
}, true);
}
}
}
AppModule
#Module(includes = ViewModelModule.class)
class AppModule {
#Singleton #Provides
BnderAPIService provideService() {
return new Retrofit.Builder()
.baseUrl("serverurl")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(new LiveDataCallAdapterFactory())
.build()
.create(APIService.class);
}
#Singleton #Provides
Db provideDb(Application app) {
return Room.databaseBuilder(app, Db.class,"Db.db").build();
}
#Singleton #Provides
UserDao provideUserDao(Db db) {
return db.userDao();
}
#Singleton #Provides
ContactDao provideContactDao(Db db) {
return db.contactDao();
}
}
FragmentBuildersModule
#Module
public abstract class FragmentBuildersModule {
#ContributesAndroidInjector
abstract AddContactsFragment contributeAddUserFragment();
#ContributesAndroidInjector
abstract ContactsFragment contributeContactsFragment();
#ContributesAndroidInjector
abstract ChalkboardFragment contributeChalkboardFragment();
}
Injectable
public interface Injectable {
}
ViewModelKey
#Documented
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
#MapKey
#interface ViewModelKey {
Class<? extends ViewModel> value();
}
ViewModelModule
#Module
abstract class ViewModelModule {
#Binds
#IntoMap
#ViewModelKey(AddContactsViewModel.class)
abstract ViewModel bindAddContactsViewModel(AddContactsViewModel addContactsViewModel);
#Binds
#IntoMap
#ViewModelKey(ContactsViewModel.class)
abstract ViewModel bindContactsViewModel(ContactsViewModel contactsViewModel);
#Binds
#IntoMap
#ViewModelKey(ChalkboardViewModel.class)
abstract ViewModel bindChalkboardViewModel(ChalkboardViewModel chalkboardViewModel);
#Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory);
}
Application
public class App extends Application implements HasActivityInjector {
#Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
#Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
}
AppInjector.init(this);
}
#Override
public DispatchingAndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
}
NavigationController
public class NavigationController {
private final int containerId;
private final FragmentManager fragmentManager;
#Inject
public NavigationController(MainActivity mainActivity) {
this.containerId = R.id.container;
this.fragmentManager = mainActivity.getSupportFragmentManager();
}
public void navigateToUsers() {
Log.i("TAG", "Navigate to users");
String tag = "users";
AddContactsFragment userFragment = AddContactsFragment.create();
fragmentManager.beginTransaction()
.replace(containerId, userFragment, tag)
.addToBackStack(null)
.commitAllowingStateLoss();
}
public void navigateToContacts() {
Log.i("TAG", "Navigate to contacts");
String tag = "contacts";
ContactsFragment contactsFragment = ContactsFragment.create();
fragmentManager.beginTransaction()
.add(contactsFragment, tag)
.addToBackStack(null)
.commitAllowingStateLoss();
}
public void navigateToChalkboard() {
Log.i("TAG", "Navigate to chalkboard");
String tag = "chalkboard";
ChalkboardFragment chalkboardFragment = ChalkboardFragment.create();
fragmentManager.beginTransaction()
.add(chalkboardFragment, tag)
.addToBackStack(null)
.commitAllowingStateLoss();
}
}
MainActivity
public class MainActivity extends AppCompatActivity implements LifecycleRegistryOwner, HasSupportFragmentInjector {
private final LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
#Inject
DispatchingAndroidInjector<Fragment> dispatchingAndroidInjector;
#Inject
NavigationController navigationController;
private Toolbar toolbar;
#Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setHandler(this);
binding.setManager(getSupportFragmentManager());
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
#Override
public DispatchingAndroidInjector<Fragment> supportFragmentInjector() {
return dispatchingAndroidInjector;
}
static class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
#BindingAdapter({"handler"})
public static void bindViewPagerAdapter(final ViewPager view, final MainActivity activity) {
final ViewPagerAdapter adapter = new ViewPagerAdapter(activity.getSupportFragmentManager());
adapter.addFragment(new ChalkboardFragment(), "Chalkboard");
adapter.addFragment(new ContactsFragment(), "Contacts");
view.setAdapter(adapter);
}
#BindingAdapter({"pager"})
public static void bindViewPagerTabs(final TabLayout view, final ViewPager pagerView) {
view.setupWithViewPager(pagerView, true);
}
}
ContactActivity
public class ContactActivity extends AppCompatActivity implements LifecycleRegistryOwner, HasSupportFragmentInjector {
private final LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
#Inject
DispatchingAndroidInjector<Fragment> dispatchingAndroidInjector;
#Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact);
if (savedInstanceState == null) {
}
}
#Override
public DispatchingAndroidInjector<Fragment> supportFragmentInjector() {
return dispatchingAndroidInjector;
}
}
"A binding with matching key exists in component" means that you have bound a dependency somewhere in your entire object graph but it cannot be reached from the subcomponent where it needs to be injected. Here is the javadoc:
Utility code that looks for bindings matching a key in all subcomponents in a binding graph so that a user is advised that a binding exists elsewhere when it is not found in the current subgraph. If a binding matching a key exists in a sub- or sibling component, that is often what the user actually wants to use.
For instance, assume you have two Activities, ActivityA and ActivityB. You generate subcomponents with #ContributesAndroidInjector and bind Foo in the ActivityA module but not the ActivityB module. If you request injection for Foo in ActivityB with #Inject Foo foo you will get that error message.
In your particular case, the error you are getting can be reproduced by:
Cloning the project from GitHub
git clone https://github.com/googlesamples/android-architecture-components.git`
Copy-pasting MainActivity into a new file ContactsActivity
Modifying MainActivityModule to look like your ActivityModule
So from this we can conclude that your ActivityModule is problematic. The #ContributesAndroidInjector is not as simple as it might seem. It actually means you are creating a new Dagger 2 subcomponent for the Activity you specify there (see the docs here).
A subcomponent can use bindings from a parent component but not sibling components. Your two lines for ContributesAndroidInjector in the ActivityModule create two sibling subcomponents: one for MainActivity and one for ContactsActivity.
However, NavigationController is dependent on MainActivity which is bound in the object graph for the MainActivity subcomponent but not in that for the ContactsActivity subcomponent. AddContactsFragment has become part of the object graph for the ContactsActivity subcomponent and doesn't have access to MainActivity anymore. This means that when Dagger 2 tries to inject the NavigationController inside your AddContactsFragment it cannot provide MainActivity as a dependency for it. This explains the "cannot provide" part of the error message.
Although it can't provide MainActivity in that particular object graph, the AndroidInjector does know in general about MainActivity hence the error message "a binding key exists". What binding key is this? A key that binds MainActivity.class to a MainActivityFactory. Where is this key bound? In your ActivityModule when you wrote the #ContributesAndroidInjector for MainActivity.
How to fix this is getting beyond scope of a StackOverflow question because it involves a lengthy refactor of the code. You would need to re-organise the object graph so that the NavigationController no longer depends on MainActivity. Perhaps you could make it depend on AppCompatActivity since that is a superclass of both your Activities. You would then need to stop using ContributesAndroidInjector and write explicit modules for your two Activities that include bindings for AppCompatActivity.
However, for now please go back to basics and start with something easier. It is a recipe for disaster to start with a complex project without a complete understanding and just modify it hoping that it will work.
The Codepath Dagger 2 tutorial project is much easier to understand and will get you familiar with the basic concepts involved in Dagger 2. Once you are comfortable with the basic concepts and have understood dependent components and sub-components, then you can attempt a more difficult example. Good luck!
I have a class that's being injected using DI via dagger. However when the activity is destroyed and recreated, the model class seems to contain the data automatically without me insert/repopulating the data.
public class MyApplication extends Application {
private ExpressionFactoryComponent mExpressionFactoryComponent;
#Override
public void onCreate() {
super.onCreate();
// Building dagger DI component
mExpressionFactoryComponent = DaggerExpressionFactoryComponent.builder().
expressionFactoryModule(new ExpressionFactoryModule(new ExpressionFactory(this))).build();
}
}
Module:
#Module
public class ExpressionFactoryModule {
private ExpressionFactory mExpressionFactory;
public ExpressionFactoryModule(ExpressionFactory expressionFactory) {
this.mExpressionFactory = expressionFactory;
}
#Provides
ExpressionFactory provideStringExpressionFactory() {
return mExpressionFactory;
}
}
The one reason for this is that ExpressionFactory is instantiated in MyApplication class and then passed into the constructor of ExpressionFactoryModule while creating ExpressionFactoryComponent. You should pass an Application instance in your module constructor and then create an instance of your class withing a metod with #Provide annotation passing that Application instance in your class's constructor.
This how things should be done with dagger. But to solve your problem you need to create another component class and build the component in an activity if you need to have an instance of your class living withing an activity only.
Here is the solution (ExpressionFactoryComponent is renamed to AppComponent here):
public class MyApplication extends Application {
private static AppComponent appComponent;
#Override
public void onCreate() {
super.onCreate();
// Building dagger DI component
appComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this)).build();
}
public static AppComponent getAppComponent() {
return appComponent;
}
}
#Component(modules = {AppModule.class})
public interface AppComponent {
Application getApplication();
void inject(App application);
}
#Module
public class AppModule {
private Application application;
public AppModule(Application application) {
this.application = application;
}
#Provides
Application provideApplication() {
return application;
}
}
#Component(dependencies = AppComponent.class, modules = {
ActivityModule.class})
public interface ActivityComponent {
void inject(MainActivity activity);
}
#Module
public class ActivityModule {
private Activity activity;
public ActivityModule(Activity activity) {
this.activity = activity;
}
#Provides
Activity provideActivity() {
return activity;
}
#Provides
ExpressionFactory provideStringExpressionFactory(Application application) {
return new ExpressionFactory(application);
}
}
public class MainActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityComponent activityComponent = DaggerActivityComponent.builder()
.activityModule(new ActivityModule(activity))
.appComponent(App.getAppComponent())
.build();
activityComponent.inject(this);
}
}
I want to add an activity as a dependency for one of my classes
class ViewHandler{
#inject public ViewHandler(Myactivity myactivity){
this.activity = myactivity;
}
}
how can I do this without being obstructed by the Activity life cycle
You need to use subscoped components with modules for this.
#Singleton
#Component(modules={SomethingModule.class})
public interface ApplicationComponent {
Something something();
}
#Module
public class SomethingModule {
#Provides
#Singleton
public Something something() {
return new Something();
}
}
#ActivityScope
#Component(dependencies={ApplicationComponent.class}, modules={MyActivityModule.class})
public interface MyActivityComponent extends ApplicationComponent {
ViewHandler viewHandler();
void inject(Myactivity myActivity);
}
#Module
public class MyActivityModule {
private Myactivity myActivity;
public MyActivityModule(Myactivity myActivity) {
this.myActivity = myActivity;
}
#Provides
public Myactivity myActivity() {
return myActivity;
}
#Provides
#ActivityScope
public ViewHandler viewHandler(Myactivity myActivity) {
return new ViewHandler(myActivity);
}
}
public class CustomApplication extends Application {
ApplicationComponent applicationComponent;
#Override
public void onCreate() {
super.onCreate();
applicationComponent = DaggerApplicationComponent.create();
}
public ApplicationComponent getApplicationComponent() {
return applicationComponent;
}
}
public class Myactivity extends AppCompatActivity {
MyActivityComponent myActivityComponent;
#Inject
ViewHandler viewHandler;
#Override
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
CustomApplication customApp = (CustomApplication)getApplicationContext();
this.myActivityComponent = DaggerMyActivityComponent.builder()
.applicationComponent(customApp.getApplicationComponent())
.myActivityModule(new MyActivityModule(this))
.build(); //preserve the state of your dependencies in onSaveInstanceState();
myActivityComponent.inject(this);
}
}
EDIT: Another option is #Subcomponent annotation
#Singleton
#Component(modules={SomethingModule.class})
public interface ApplicationComponent {
Something something();
MyActivityComponent newMyActivityComponent(MyActivityModule myActivityModule);
}
#ActivityScope
#Subcomponent(modules={MyActivityModule.class})
public interface MyActivityComponent {
ViewHandler viewHandler();
void inject(Myactivity myActivity);
}
public class Myactivity extends AppCompatActivity {
MyActivityComponent myActivityComponent;
#Inject
ViewHandler viewHandler;
#Override
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
CustomApplication customApp = (CustomApplication)getApplicationContext();
this.myActivityComponent = customApp.getApplicationComponent()
.newMyActivityComponent(new MyActivityModule(this));
myActivityComponent.inject(this);
}
}
Let's say I have three Dagger modules:
#Module()
public class MainModule {
private Application application;
public MainModule(Application application) {
this.application = application;
}
#Provides
#Singleton
Application provideApplication() {
return application;
}
#Provides
Something provideSomething(Application application) {
return new Something(application);
}
}
#Module()
public class SubModule1 {
private Activity activity;
public SubModule1(Activity activity) {
this.activity = activity;
}
#Provides
#Singleton
Activity provideActivity() {
return activity;
}
#Provides
SomethingElse provideSomethingElse(Activity activity) {
return new SomethingElse(activity);
}
}
#Module()
public class SubModule2 {
private Activity activity;
public SubModule2(Activity activity) {
this.activity = activity;
}
#Provides
#Singleton
Activity provideActivity() {
return activity;
}
#Provides
Anything provideAnything(Activity activity) {
return new Anything(activity);
}
}
Now assuming I want to do something like this:
public class MyApplication extends Application {
...
#Override
public void onCreate() {
super.onCreate();
objectGraph = ObjectGraph.create(new MainModule(this));
objectGraph.inject(this);
}
}
public class MyActivity1 extends Activity {
...
#Override
public void onCreate() {
super.onCreate();
objectGraph = ((MyApplication) getApplication()).getObjectGraph().plus(new SubModule1(this)
objectGraph.inject(this);
}
}
public class MyActivity2 extends Activity {
...
#Override
public void onCreate() {
super.onCreate();
objectGraph = ((MyApplication) getApplication()).getObjectGraph().plus(new SubModule2(this)
objectGraph.inject(this);
}
}
It also might happen that I have such a class:
public class TestClass {
#Inject
SomethingElse somethingElse;
#Inject
Anything anything;
}
What is the right way to implement this? How should I use includes, addsTo, injects, library, complete and plus()?
I usually set Dagger up as follows:
Extend Application like this:
public class InjectingApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
objectGraph = ObjectGraph.create(new MainModule(this));
objectGraph = ObjectGraph.create(new SubModule1(this));
objectGraph = ObjectGraph.create(new ActivityModule());
objectGraph.inject(this);
}
}
Then have a module for adding references to your Activities (called ActivityModule.java in this instance):
#Module(
injects = {
MyActivity1.class,
MyActivity2.class }
) public class ActivityModule { }
Then your Activities will look like this:
public class MyActivity1 extends Activity {
#Inject
Something something;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((InjectingApplication) getApplication()).inject(this);
}
}
Finally, your modules will look like this:
#Module()
public class MainModule {
private Context context;
public MainModule(Context context) {
this.context = context;
}
#Provides
Something provideSomething(Context context) {
return new Something(context);
}
}
#Module()
public class SubModule1 {
private Context context;
public SubModule1(Context context) {
this.context = context;
}
#Provides
SomethingElse provideSomethingElse(Context context) {
return new SomethingElse(context);
}
}