web-dev-qa-db-fra.com

Comment demander une injection dans des fragments et services Android?

Je suis ce tutoriel pour ajouter Dagger 2 à mon projet Android.

Après avoir configuré et créé les modules et les composants, je peux ajouter les dépendances dans une activité comme celle-ci:

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

J'ai du mal à injecter des dépendances dans Fragment and IntentService?

public class FragmentBrandList extends ListFragment {
}

Dans cette classe, quelle méthode @Override dois-je demander l'injection et quel sera le code pour cela?

9
Devesh Agrawal

Dans cette classe, quelle méthode @Override je devrais utiliser et quel sera le code pour ajouter la dépendance dans fragment?

Le bon endroit pour appeler l'injection à l'intérieur d'un fragment est onAttach(Context context). Ceci est indiqué dans la section où injecter du guide de l'utilisateur Dagger 2 ici

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

Le bon endroit pour appeler une injection dans un service est onCreate()

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

}

Notez que dans les deux cas, la demande d’injection intervient avant l’appel de super.onCreate(). Le manuel d'utilisation de la dague l'explique comme suit:

Il est essentiel d'appeler AndroidInjection.inject () avant super.onCreate () dans une activité, car l'appel à super attache des fragments de l'instance d'activité précédente lors du changement de configuration, qui injecte à son tour les fragments. Pour que l'injection de fragment réussisse, il faut que l'activité soit déjà injectée. Pour les utilisateurs de ErrorProne, le fait d'appeler AndroidInjection.inject () après super.onCreate () est une erreur du compilateur.

En d'autres termes:

  1. L’appel Activité super.onCreate() rattache des fragments d’une instance précédente 
  2. Cet appel super provoque la réinjection de fragments (puisque les fragments sont injectés dans onAttach)
  3. Les fragments doivent être injectés après que leur activité ait été injectée. Demandez donc une injection dans votre activité avant d'appeler super.onCreate().

Vous pouvez toujours vérifier où injecter en consultant le code source correspondant aux classes com.google.dagger:dagger-Android telles que DaggerFragment et DaggerService. Voir le dépôt GitHub ici

Pour votre exemple spécifique, assurez-vous d’avoir ajouté les nouveaux sites d’injection au NetComponent:

void inject(FragmentBrandList frag);

void inject(BrandListService service);
13
David Rawson

Étape 1: Créez votre 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");
    }

}

Étape 2: Créez votre composant d'application:

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

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

    void inject(DogSyncService service);
}

Étape 3: Créer une classe d’ID:

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(){}
}

Dernière étape: Injectez n’importe où en utilisant:

DependencyInjector.applicationComponent()

Votre question m'a inspiré pour créer un projet de démonstration montrant l'injection d'activité, de fragment et de service à l'aide de Dagger2. Voici le git: https://github.com/write2sv/AndroidDIDagger2/tree/master/app/src/main/Java/work/shaggy/didemo

7
write2sv

Je l'ai fait en utilisant ((AppController) getActivity().getApplication()).getNetComponent().inject(this);

dans la méthode Fragment.onCreate().

1
Rumid
((MyApp) context.getApplicationContext()).getApplicationComponent().inject(MyFragment.this);

J'ai ajouté ceci dans la méthode onAttach(Context context) du fragment.

0
Adi

Vous pouvez utiliser Autadogger pour éviter d'avoir à écrire tout ce passe-partout. J'utilise cette architecture assez souvent:

build.gradle

apt 'com.github.lukaspili.autodagger2:autodagger2-compiler:1.1'
compile 'com.github.lukaspili.autodagger2:autodagger2:1.1'

YourApp.Java

@AutoComponent( modules = YourApp.YourAppModule.class )
public class YourApp extends Application {

    private static YourApp instance;
    private YourAppComponent component;

    public YourAppComponent getComponent() {
        return this.component;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        setupComponent();
    }

    private void setupComponent() {
        component = DaggerYourAppComponent.builder()
                .yourAppModule(new YourAppModule(instance))
                .build();
    }


    @dagger.Module
    public static class YourAppModule {
        private YourApp app;

        YourAppModule(YourAppApp application) {
            this.app = application;
        }

        @Provides @AutoExpose(YourApp.class)
        Application provideApplication() {
            return app;
        }

        @Provides @AutoExpose(PoswalaApp.class)
        Context provideContext() {
            return app;
        }

        @Provides @AutoExpose(YourApp.class)
        Retrofit provideApiAdapter() {
            return ApiService.getServiceInstance();
        }
    }
}

YourActivity.Java

@AutoComponent(
    dependencies = YourApp.class,
    modules = YourActivity.YourActivityModule.class
)

public class YourActivity extends BaseActivity implements YourActivityView {

    private YourActivityComponent component;
    @Inject MyPresenter presenter

    // This is an abstract method from BaseActivity
    @Override
    protected void setupComponent(YourAppComponent appComponent) {
        component = DaggerYourActivityComponent.builder()
                .yourAppComponent(((YourApp) getApplication()).getComponent())
                .yourActivityModule(new YourctivityModule(this))
                .build();
    }

    @Override
    protected MyPresenter getPresenter() {
        return presenter;
    }


    @dagger.Module
    public static class YourActivityModule {

        private YourActivityView view;

        YourActivityModule(YourActivityView view) {
            this.view = view;
        }


        @Provides @AutoExpose(YourActivity.class)
        YourActivityView provideView() {
            return view;
        }

        // Your other dependencies
    }
}

Explication rapide:

Le module de votre application devra avoir une dépendance "universelle", mais vous pourrez ainsi utiliser plusieurs modules pour une classe. Vous avez juste besoin de personnaliser le 

@AutoComponent(
    dependencies = YourApp.class,
    modules = { YourActivity.YourActivityModule.class, YourFragment.YourFragmentModule.class }
)

bloc. Vous pouvez ajouter autant de modules que vous le souhaitez en utilisant cette syntaxe.

J'espère que cela vous aide

0
Chisko

Vous avez vraiment besoin d'inclure la méthode d'injection pour ce que vous voulez injecter. 

@Singleton
@Component
public interface AppComponent {
    void inject(MainActivity activity);
    void inject(FragmentBrandList fragmentBrandList);
} 
0
EpicPandaForce