如何注入 BroadcastReceiver
How to inject into a BroadcastReceiver
是否有人必须使用 dagger 将已经存在的 class 和一些业务逻辑注入到 BroadcastReceiver 中?
我正在使用 dagger 1 并且已经找到了一个很好的示例 (https://github.com/adennie/fb-android-dagger) 但是,我找不到如何添加属于不同模块的已经存在的 class,进入 BroadcastReceiver。
如有任何帮助或建议,我们将不胜感激。
我设法通过定义一个提供我需要的用例的模块将用例注入我的广播,我在 onReceive 方法上添加了模块,检查下面的代码:
我的 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;
}
与注入 Activity
相同
public void onReceive(Context context, Intent intent) {
((Application) context.getApplicationContext()).getInjector().inject(this);
}
回答这个问题可能为时已晚,但我将提供一个我最近的项目中的示例,在该项目中我尝试注入 AppWidgetProvider
,它是 [=16= 的直接子 class ].
我们需要将改装服务注入 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);
}
}
为带有 @ContributesAndroidInjector
注释的抽象方法创建另一个抽象 @Module
,您要注入 return BroadcastReceiver
s:
/**
* To inject the app widgets.
*/
@Module
public abstract class WidgetsModule {
@ContributesAndroidInjector
abstract IngredientsWidget contributesIngredientsWidget();
}
如果你忘记添加这个模块,你会得到这样的错误:
java.lang.IllegalArgumentException: No injector factory bound for
Class<>
然后是包含两个模块的组件,除了AndroidInjectionModule
@Singleton
@Component(modules = {AndroidInjectionModule.class, NetModule.class, WidgetsModule.class})
public interface AppComponent {
void inject(RecipesApp recipesApp);
}
然后在您的 Application
class 中实现 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>()
}
申请class
class MyApp : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<MyApp> =
DaggerAppComponent.builder().create(this@MyApp)
}
BroadcastReceiver class
class MyTestReceiver : BroadcastReceiver() {
@Inject
lateinit var anInjectedObject: MyInjectObject
override fun onReceive(context: Context, intent: Intent) {
AndroidInjection.inject(this, context)
anInjectedObject.doSomthing()
}
}
您可以使用 DaggerBroadcastReceiver 或重写 onReceive 方法,如下所示:
public void onReceive(Context context, Intent intent) {
AndroidInjection.inject(this, context);
// your code should be here ...
}
匕首文档:
https://dagger.dev/api/2.24/dagger/android/DaggerBroadcastReceiver
有点晚了,但我比以前的答案略有改进,您不需要在 onReceive
方法中显式调用 AndroidInjection.inject(this, context);
。
这是接收器,所以你不必这样做,技巧是从 DaggerBroadcastReceiver
:
class MyReceiver : DaggerBroadcastReceiver() {
@Inject
lateinit var repository: MyRepository
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent)
// Do your stuff...
}
}
剩下的就是注册模块等,希望对你有帮助:D
- 以前的解决方案现在在最新的 Hilt 版本中不再有效,因为 Hilt 没有任何称为 AndroidInjection 的函数。
- App Widget Provider 扩展了广播接收器。所以你可以像这样简单地注释任何广播接收器:
答案:
@AndroidEntryPoint
class StandardWidgetProvider : AppWidgetProvider() {
@Inject
lateinit var room: AppDatabase
override fun onReceive(context: Context, intent: Intent?) {
super.onReceive(context, intent)
// do your stuff here
}
}
在 KOIN 依赖注入中,
class ServiceClass1()
class LazyServiceClass2()
// 在 Activity 中不需要 KoinComponent
class MyActivity: AppCompatActivity() {
// evaluates dependency eagerly
val service: ServiceClass1= get()
// evaluates dependency lazily
val lazyService: LazyServiceClass2by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// does something with services
}
}
但是对于 Receiver,像下面这样扩展“KoinComponent”
// In non-lifecycle component, KoinComponent is needed
class SomeBroadcastReceiver: BroadcastReceiver(), KoinComponent {
// evaluates dependency eagerly
val service: Service1 = get()
// evaluates dependency lazily
val lazyService: LazyService2 by inject()
override fun onReceive(context: Context?, intent: Intent?) {
// does something with services
}
}
希望对你有用。
是否有人必须使用 dagger 将已经存在的 class 和一些业务逻辑注入到 BroadcastReceiver 中?
我正在使用 dagger 1 并且已经找到了一个很好的示例 (https://github.com/adennie/fb-android-dagger) 但是,我找不到如何添加属于不同模块的已经存在的 class,进入 BroadcastReceiver。
如有任何帮助或建议,我们将不胜感激。
我设法通过定义一个提供我需要的用例的模块将用例注入我的广播,我在 onReceive 方法上添加了模块,检查下面的代码:
我的 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;
}
与注入 Activity
相同public void onReceive(Context context, Intent intent) {
((Application) context.getApplicationContext()).getInjector().inject(this);
}
回答这个问题可能为时已晚,但我将提供一个我最近的项目中的示例,在该项目中我尝试注入 AppWidgetProvider
,它是 [=16= 的直接子 class ].
我们需要将改装服务注入 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);
}
}
为带有 @ContributesAndroidInjector
注释的抽象方法创建另一个抽象 @Module
,您要注入 return BroadcastReceiver
s:
/**
* To inject the app widgets.
*/
@Module
public abstract class WidgetsModule {
@ContributesAndroidInjector
abstract IngredientsWidget contributesIngredientsWidget();
}
如果你忘记添加这个模块,你会得到这样的错误:
java.lang.IllegalArgumentException: No injector factory bound for Class<>
然后是包含两个模块的组件,除了AndroidInjectionModule
@Singleton
@Component(modules = {AndroidInjectionModule.class, NetModule.class, WidgetsModule.class})
public interface AppComponent {
void inject(RecipesApp recipesApp);
}
然后在您的 Application
class 中实现 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>()
}
申请class
class MyApp : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<MyApp> =
DaggerAppComponent.builder().create(this@MyApp)
}
BroadcastReceiver class
class MyTestReceiver : BroadcastReceiver() {
@Inject
lateinit var anInjectedObject: MyInjectObject
override fun onReceive(context: Context, intent: Intent) {
AndroidInjection.inject(this, context)
anInjectedObject.doSomthing()
}
}
您可以使用 DaggerBroadcastReceiver 或重写 onReceive 方法,如下所示:
public void onReceive(Context context, Intent intent) {
AndroidInjection.inject(this, context);
// your code should be here ...
}
匕首文档: https://dagger.dev/api/2.24/dagger/android/DaggerBroadcastReceiver
有点晚了,但我比以前的答案略有改进,您不需要在 onReceive
方法中显式调用 AndroidInjection.inject(this, context);
。
这是接收器,所以你不必这样做,技巧是从 DaggerBroadcastReceiver
:
class MyReceiver : DaggerBroadcastReceiver() {
@Inject
lateinit var repository: MyRepository
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent)
// Do your stuff...
}
}
剩下的就是注册模块等,希望对你有帮助:D
- 以前的解决方案现在在最新的 Hilt 版本中不再有效,因为 Hilt 没有任何称为 AndroidInjection 的函数。
- App Widget Provider 扩展了广播接收器。所以你可以像这样简单地注释任何广播接收器:
答案:
@AndroidEntryPoint
class StandardWidgetProvider : AppWidgetProvider() {
@Inject
lateinit var room: AppDatabase
override fun onReceive(context: Context, intent: Intent?) {
super.onReceive(context, intent)
// do your stuff here
}
}
在 KOIN 依赖注入中,
class ServiceClass1()
class LazyServiceClass2()
// 在 Activity 中不需要 KoinComponent
class MyActivity: AppCompatActivity() {
// evaluates dependency eagerly
val service: ServiceClass1= get()
// evaluates dependency lazily
val lazyService: LazyServiceClass2by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// does something with services
}
}
但是对于 Receiver,像下面这样扩展“KoinComponent”
// In non-lifecycle component, KoinComponent is needed
class SomeBroadcastReceiver: BroadcastReceiver(), KoinComponent {
// evaluates dependency eagerly
val service: Service1 = get()
// evaluates dependency lazily
val lazyService: LazyService2 by inject()
override fun onReceive(context: Context?, intent: Intent?) {
// does something with services
}
}
希望对你有用。