Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger 2: How to use injection with a Fragment

I'm using AndroidInjection.inject(this) to inject components into an activity.

AndroidInjection also has an overloaded method that takes android.app.Fragment as a parameter. But my fragments extend android.support.v4.app.Fragment and there is no corresponding method.

Question: How to use injection if a fragment extends android.support.v4.app.Fragment?

like image 765
Sasha Shpota Avatar asked Sep 17 '18 21:09

Sasha Shpota


People also ask

How do you inject a fragment?

Injecting a Fragment is just as simple as injecting an Activity . Define your subcomponent in the same way. Instead of injecting in onCreate() as is done for Activity types, inject Fragment s to in onAttach() . Unlike the modules defined for Activity s, you have a choice of where to install modules for Fragment s.

How does a Dagger injection work?

Dagger automatically generates code that mimics the code you would otherwise have hand-written. Because the code is generated at compile time, it's traceable and more performant than other reflection-based solutions such as Guice. Note: Use Hilt for dependency injection on Android.

How do you inject a ViewModel with a Dagger?

Setup a Dagger 2 Module Then setup the Dagger 2 Module with that provide the ViewModel. Like normal ViewModel creation, use ViewModelProvider and the Factory to create it. We'll need to pass in the dependencies which can be automatically injected by Dagger 2 using the conventional approach.

Can a Dagger inject a private field?

One of the considerations with Dagger is that injected fields cannot be private. They need to have at least package-private visibility like in the preceding code. Note: Field injection should only be used in Android framework classes where constructor injection cannot be used.


1 Answers

For support library fragments you need to use support injection. Here some example:

@Singleton
@Component(modules = {
        AndroidSupportInjectionModule.class, // Important
        ActivityModule.class,
        FragmentModule.class
})

public interface AppComponent extends AndroidInjector<App> {

    void inject(App app);

    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);
        AppComponent build();
    }
}

Application, you can use DaggerApplication or simple HasSomeIjection if you need for example Multidex implementation:

public class App extends MultiDexApplication implements
    HasActivityInjector,
    HasFragmentInjector {

    @Inject DispatchingAndroidInjector<Activity> activityInjector;
    @Inject DispatchingAndroidInjector<Fragment> fragmentInjector;
    private AppComponent mComponent;

    @Override
    public void onCreate() {
        mComponent = DaggerAppComponent.builder().application(this).build();
        mComponent.inject(this);
    }

    // Dependency Injection
    @Override
    public DispatchingAndroidInjector<Activity> activityInjector() {
        return activityInjector;
    }

    @Override
    public DispatchingAndroidInjector<Fragment> fragmentInjector() {
        return fragmentInjector;
    }
}

Next module:

@Module
public abstract class FragmentModule {
    @ContributesAndroidInjector
    abstract ContactsFragment bindContactsFragment();
}

Activity module:

@Module
public abstract class ActivityModule {
    @ContributesAndroidInjector
    abstract ContactsActivity bindContactsActivity();
}

And fragment:

import com.some.ContactsPresenter;
import dagger.android.support.DaggerFragment;

public class ContactsFragment extends DaggerFragment {

    @Inject
    ContactsPresenter mContactsPresenter;

    // .....
}

If you don't want use the DaggerFragment, you can open its implementation and copied to your fragment with necessary changes. The main feature here is using AndroidSupportInjectionModule. Hope this will help you

like image 125
dantes_21 Avatar answered Sep 29 '22 12:09

dantes_21