Search code examples
androiddependency-injectiondagger-2dagger

Dagger 2 - Pass FragmentManager to constructor


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 

Solution

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