car*_*iel 16 android dependency-injection broadcastreceiver dagger
有人已经不得不使用匕首将已经存在的类(带有一些业务逻辑)注入BroadcastReceiver吗?
我正在使用dagger 1并且已经找到了一个很好的例子(https://github.com/adennie/fb-android-dagger)但是,我找不到如何添加一个已经存在的类,它属于一个不同的模块,进入BroadcastReceiver.
任何帮助或建议将不胜感激.
Cha*_*lan 22
与注入活动相同
public void onReceive(Context context, Intent intent) {
        ((Application) context.getApplicationContext()).getInjector().inject(this);
    }
amr*_*rro 18
回答这个问题可能为时已晚,但我将从我最近的项目中提供一个例子,我试图注入AppWidgetProvider它是一个直接的子类BroadcastReceiver.
我们需要在以下方面注入改造服务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);
    }
}
@Module使用带有要注入的@ContributesAndroidInjector返回值BroadcastReceiver的抽象方法创建另一个抽象:
/**
 * To inject the app widgets.
 */
@Module
public abstract class WidgetsModule {
    @ContributesAndroidInjector
    abstract IngredientsWidget contributesIngredientsWidget();
}
如果您忘记添加此模块,您将收到如下错误:
java.lang.IllegalArgumentException:没有为Class <>绑定的进程工厂
然后是具有两个模块的组件 AndroidInjectionModule
@Singleton
@Component(modules = {AndroidInjectionModule.class, NetModule.class, WidgetsModule.class})
public interface AppComponent {
    void inject(RecipesApp recipesApp);
}
然后在你的Application类中实现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;
    }
}
最后,您可以在调用super()之前将您的BroadcastReceiver注入onReceive().
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);
    }
}
您可以找到有关如何注入android组件文档的更多信息.
我建了一个小样本:广播注入.
s-h*_*ter 10
Dagger 2示例,用于将对象注入到BroadcastReceiver中。
BroadcastReceiverModule.kt
@Module
abstract class BroadcastReceiverModule {
    @ContributesAndroidInjector
    abstract fun contributesMyTestReceiver() : MyTestReceiver
}
AppComponent.kt
@Singleton
@Component(
        modules = [
            (AndroidSupportInjectionModule::class),
            (BroadcastReceiverModule::class)
        ])
interface AppComponent : AndroidInjector<MyApp> {
    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}
应用类
class MyApp : DaggerApplication() {
    override fun applicationInjector(): AndroidInjector<MyApp> =
            DaggerAppComponent.builder().create(this@MyApp)
}
BroadcastReceiver类
class MyTestReceiver : BroadcastReceiver() {
    @Inject
    lateinit var anInjectedObject: MyInjectObject
    override fun onReceive(context: Context, intent: Intent) {
        AndroidInjection.inject(this, context)
        anInjectedObject.doSomthing()
    }
}
只是有点太晚了,但我比以前的答案略有改进,您不需要显式调用AndroidInjection.inject(this, context);方法onReceive。
这是接收器,所以你不必这样做,技巧是从以下延伸的DaggerBroadcastReceiver:
class MyReceiver : DaggerBroadcastReceiver() {
    @Inject
    lateinit var repository: MyRepository
    override fun onReceive(context: Context?, intent: Intent?) {
        super.onReceive(context, intent)
        // Do your stuff...
    }
}
其余的与注册模块等相同。我希望它有所帮助:D
我设法通过定义提供我需要的用例的模块将用例注入到我的广播中,然后在 onReceive 方法上添加该模块,检查下面的代码:
我的广播接收器模块:
@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;
    }
}
我的广播接收器:
@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;
}