有人已经不得不使用匕首将已经存在的类(带有一些业务逻辑)注入BroadcastReceiver吗?
我正在使用匕首1并且已经找到了一个很好的例子(https://github.com/adennie/fb-android-dagger)但是,我找不到如何将已经存在的类(属于不同的模块)添加到BroadcastReceiver中。
任何帮助或建议将不胜感激。
与注入活动相同
public void onReceive(Context context, Intent intent) {
((Application) context.getApplicationContext()).getInjector().inject(this);
}
回答这个问题可能为时已晚,但我将从我最近的项目中提供一个例子,我试图注入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
s:
/**
* 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组件docs的信息。
我建了一个小样本:broadcast-injection。
用于将对象注入BroadcastReceiver的Dagger 2示例。
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>()
}
Application类
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()
}
}
我设法通过定义一个提供我需要的用例的模块将用例注入我的广播,并在onReceive方法上添加Module,检查下面的代码:
我的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;
}
}
我的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;
}