user4260260
user4260260

Reputation:

How to properly inject fragments for a single activity App

I'm using dagger2 in my project. Project follows MVP pattern. My app design is like I'm using a single activity throught my application. All UI elemets are in Fragments and the single activity acts as the host activity for all the fragments in the project. Each module in my project will be using a fragment as the UI component like LoginFragment, SplashScreenFragment,RegistrationFragment, HomeScreenFragment.

So basically my activity will be launched only once, and it contains a fragment container only, where fragments will be replaced when user navigates to each screens in each module.

each time user moves from one screen to another, instead of creating an activity it , It will just invoke a gotoNextScreen in the activity, which will then inflate the next fragment

So My activity will be doing the following operations only

Since I have n number of screens (n number of fragmetns and presenters), I cannot use field injection on activity like

            public class MainActivity{
                @Inject RegistrationFragment registrationFragment;
                @Inject LoginFragment loginFragment
            }

because the number of field will be huge, also at a time we need only one fragment and one presenter. So what I did is , I created seperate components for each module , made it as a dependent component of my main App component. Now my activity looks like this.

            public void gotoNextScreen(ScreenType screentype, Data data){

                        switch(screentype){
                            case LOGIN:
                                 DaggerLoginComponent.builder()
                                                .appComponent(mAppComponent)                        
                                                .build();
                                 // get login fragment and presenter from login component and inflate               
                                 break;

                            case REGISTRATION:
                                 DaggerLoginComponent.builder()
                                                .appComponent(mAppComponent)                        
                                                .build();
                               // get registration fragment and presenter from registration component and inflate               

                             // and the switch case goes on like this

                        }
        }

I find it very difficult because I'm almost repeating the code in each and every module. Im creating different components just for different fragmet types and presenters.

Can I simplify using generics or something like that? Does dagger provide any simple way to solve this kind of problem? Can anyone show some sample code to solve this?

Upvotes: 2

Views: 682

Answers (1)

Eselfar
Eselfar

Reputation: 3869

I don't know if it's the right approach either as I'm quite new with Dagger2 and MVP too but I've implemented it like that:

The Fragment has a callback to the Activity as explained in the official documentation.

The callback as a gotoNextScreen method. The goToNextScreen (implemented by the Activity), calls the Activity presenter.

This presenter is in charge of instantiating the Fragment and call a displayFragment method on the View (the Activity). Like that the Activity doesn't know anything about the implementation. It just passes the information to the presenter and then display the Fragment.

It look like that:

FragmentA

public void onNext(){
   mActivityCallback.gotoNextScreen(screentype, data);
}

The Activity

public void gotoNextScreen(ScreenType screentype, Data data){
   mPresenter.goToNext(screentype, data);
}

public void displayFragment(Fragment f){
   // Code to replace the current Fragment by the fragment f
}

The Activity Presenter

public void goToNext(ScreenType screentype, Data data){
   Fragment f;
   switch(screentype){
      case A:
          f = FragmentA.newInstance(data);
          break;
      case B:
          f = FragmentB.newInstance(data);
          break;
      ...
   }
   mView.displayFragment(f); // mView is the Activity
}

As I said, I'm not sure this implementation is valid as:

  • You have 2 times the same gotoNextScreen method (in the Activity and the Presenter)
  • The presenter deals with Fragment (which are Android objects).
  • The Fragment is not injected.

EDIT

Dagger part:

The Activity is injected when created:

MainActivityComponent component = ((CustomApplication) getApplication()).getComponent()
                .plus(new MainActivityModule());

Same with the Fragment:

The callback to the activity has a getComponent method and when the Fragment is attached, it calls:

public void onAttach(Context context) {
   //...
    activityCallback.getComponent().inject(FragmentA.this)
}

Upvotes: 1

Related Questions