web-dev-qa-db-fra.com

Comment injecter dans un BroadcastReceiver

Quelqu'un a-t-il déjà dû injecter une classe déjà existante, avec une logique métier, dans un BroadcastReceiver à l'aide d'un poignard?

J'utilise la dague 1 et j'ai déjà trouvé un bel exemple ( https://github.com/adennie/fb-Android-dagger ) mais je n'ai pas trouvé comment ajouter une classe déjà existante , qui appartient à un module différent, dans un BroadcastReceiver.

Toute aide ou conseil serait grandement apprécié.

18
carlosmaciel

J'ai réussi à injecter des cas d'utilisation dans ma diffusion en définissant un module qui fournit les cas d'utilisation dont j'ai besoin et j'ajoute le module sur la méthode onReceive, vérifiez le code ci-dessous:

Mon BroadcastReceiverModule:

@Module(injects = { MyBroadcastReceiver.class }, addsTo = MyAppModule.class)
public class BroadcastReceiverModule {
    @Provides @Singleton MyUtilsClass providesMyUtilsClass(MyUtilsClassImpl myUtilsClass) {
        return myUtilsClass;
    }
    @Provides @Singleton MyUseCase providesMyUseCase(MyUseCaseImpl myUseCaseUtils) {
        return myUseCaseUtils;
    }
}

Mon BroadCastReceiver:

@Inject MyUtilsClass myUtilsClass;
@Inject MyUseCase myUseCase;
@Override public void onReceive(Context context, Intent intent) {
    AcidApplication.getScopedGraph(getModules().toArray()).inject(this);
    myUseCase.call();
    myUtilsClass.doSomething();
}
protected List<Object> getModules() {
    List<Object> result = new ArrayList<>();
    result.add(new BroadcastReceiverModule());
    return result;
}
4
carlosmaciel

Identique à l'injection dans une activité

public void onReceive(Context context, Intent intent) {
        ((Application) context.getApplicationContext()).getInjector().inject(this);
    }
22
Chatura Dilan

Il est peut-être trop tard pour répondre à cette question, mais je fournirai un exemple de mon récent projet où j'ai essayé d'injecter AppWidgetProvider qui est une sous-classe directe de BroadcastReceiver.

Nous devons injecter un service de mise à niveau dans un BroadcastReceiver:

@Module
public class NetModule {
    /** shrunk for simplicity's sake. **/
    @Singleton
    @Provides
    public WidgetService provideWidgetService(Application application, OkHttpClient client, Gson gson) {
        return new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(application.getString(R.string.api_url))
                .client(client)
                .build()
                .create(WidgetService.class);
    }
}

Créez un autre résumé @Module pour les méthodes abstraites annotées de @ContributesAndroidInjector qui renvoient BroadcastReceivers que vous souhaitez injecter:

/**
 * To inject the app widgets.
 */
@Module
public abstract class WidgetsModule {
    @ContributesAndroidInjector
    abstract IngredientsWidget contributesIngredientsWidget();
}

Si vous avez oublié d'ajouter ce module, vous obtiendrez une erreur comme:

Java.lang.IllegalArgumentException: aucune fabrique d'injecteurs liée pour la classe <>

Ensuite, le composant avec les deux modules, en plus AndroidInjectionModule

@Singleton
@Component(modules = {AndroidInjectionModule.class, NetModule.class, WidgetsModule.class})
public interface AppComponent {
    void inject(RecipesApp recipesApp);
}

Ensuite, dans votre classe Application, vous implémentez l'interface HasBroadcastReceiverInjector.

public class RecipesApp extends Application implements HasBroadcastReceiverInjector {

    @Inject
    DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector;

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

        component().inject(this);
    }

    public AppComponent component() {
        return DaggerAppComponent.builder()
                .build();
    }

    @Override
    public AndroidInjector<BroadcastReceiver> broadcastReceiverInjector() {
        return broadcastReceiverInjector;
    }
}

Enfin, vous pouvez injecter votre BroadcastReceiver dans onReceive () avant d'appeler le super ().

public class IngredientsWidget extends AppWidgetProvider {

    @Inject
    public WidgetService api;


    @Override
    public void onReceive(Context context, Intent intent) {
        /** Don't forget this line **/
        AndroidInjection.inject(this, context);
        super.onReceive(context, intent);
    }

}

Vous pouvez en savoir plus sur la façon d'injecter Android composants docs .

J'ai construit un petit échantillon: diffusion-injection .

19
amrro

Exemple Dagger 2 pour injecter des objets dans un BroadcastReceiver.

Le BroadcastReceiverModule.kt

@Module
abstract class BroadcastReceiverModule {
    @ContributesAndroidInjector
    abstract fun contributesMyTestReceiver() : MyTestReceiver
}

The AppComponent.kt

@Singleton
@Component(
        modules = [
            (AndroidSupportInjectionModule::class),
            (BroadcastReceiverModule::class)
        ])
interface AppComponent : AndroidInjector<MyApp> {
    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}

La classe Application

class MyApp : DaggerApplication() {
    override fun applicationInjector(): AndroidInjector<MyApp> =
            DaggerAppComponent.builder().create(this@MyApp)
}

La classe BroadcastReceiver

class MyTestReceiver : BroadcastReceiver() {

    @Inject
    lateinit var anInjectedObject: MyInjectObject

    override fun onReceive(context: Context, intent: Intent) {
        AndroidInjection.inject(this, context)
        anInjectedObject.doSomthing()
    }
}
12
s-hunter

Vous pouvez utiliser DaggerBroadcastReceiver ou vous pouvez remplacer la méthode onReceive comme ci-dessous:

public void onReceive(Context context, Intent intent) {
    AndroidInjection.inject(this, context);
    // your code should be here ...
}

documents de poignard: https://dagger.dev/api/2.24/dagger/Android/DaggerBroadcastReceiver

1