Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I request injection in Android Fragments and Services?

I'm following this tutorial to add Dagger 2 to my Android project.

After doing setup and creating the modules and components I can add the dependencies in an Activity like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_account);
    ButterKnife.bind(this);
    ((AppController) getApplication()).getNetComponent().inject(this);
}

I am struggling in how to inject dependencies in a Fragment and IntentService?

public class FragmentBrandList extends ListFragment {
}

In this class which @Override method should I request injection in and what will be the code for this?

like image 733
Devesh Agrawal Avatar asked Dec 23 '16 15:12

Devesh Agrawal


2 Answers

In this class which @Override method i should use and what will be the code to add dependency in fragment?

The correct place to call injection inside a Fragment is onAttach(Context context). This is stated in the where to inject section of the Dagger 2 user guide here

@Override
public void onAttach(Context context) {
    ((AppController) context.getApplicationContext()).getNetComponent().inject(this);
    super.onAttach(context);
}

The correct place to call injection inside a Service is onCreate()

@Override 
public void onCreate() {
    ((AppController) getApplication()).getNetComponent().inject(this);
    super.onCreate();

}

Note that in both cases the request for injection comes before the call to super.onCreate(). The Dagger user guide explains it like this:

It is crucial to call AndroidInjection.inject() before super.onCreate() in an Activity, since the call to super attaches Fragments from the previous activity instance during configuration change, which in turn injects the Fragments. In order for the Fragment injection to succeed, the Activity must already be injected. For users of ErrorProne, it is a compiler error to call AndroidInjection.inject() after super.onCreate().

In other words:

  1. The Activity super.onCreate() call re-attaches Fragments from a previous instance
  2. This super call in cause Fragments to be re-injected (since Fragments are injected in onAttach)
  3. Fragments should be injected after their Activity is injected, therefore request injection in your Activity before calling super.onCreate().

You can always check where to inject by looking at the relevant source code for the com.google.dagger:dagger-android classes like DaggerFragment and DaggerService. See the GitHub repo here

For your specific example, please make sure you have added the new injection sites to the NetComponent:

void inject(FragmentBrandList frag);

void inject(BrandListService service);
like image 189
David Rawson Avatar answered Sep 22 '22 02:09

David Rawson


Step 1: Create your ApplicationModule

@Module
public class ApplicationModule {

    private final DIApplication application;

    public ApplicationModule(DIApplication application) {
        this.application = application;
    }

    @Provides @Singleton
    public DIApplication provideApplication() {
        return application;
    }

    @Provides @Singleton
    public DogModel provideDogModel() {
        return new DogModelImpl("Scooby-doo");
    }

}

Step 2: Create your ApplicationComponent:

@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
    void inject(DIApplication application);

    void inject(BaseActivity activity);
    void inject(BaseFragment fragment);

    void inject(DogSyncService service);
}

Step 3: Create a DI Class:

public class DependencyInjector {

    private static ApplicationComponent applicationComponent;

    public static void initialize(DIApplication diApplication) {
        applicationComponent = DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(diApplication))
                .build();
    }

    public static ApplicationComponent applicationComponent() {
        return applicationComponent;
    }

    private DependencyInjector(){}
}

Final Step: Inject anywhere using:

DependencyInjector.applicationComponent()

Your question inspired me to create a Demo project that shows Activity, Fragment and Service injection using Dagger2. Here is the git: https://github.com/write2sv/AndroidDIDagger2/tree/master/app/src/main/java/work/shaggy/didemo

like image 43
write2sv Avatar answered Sep 20 '22 02:09

write2sv