如何注入 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 BroadcastReceivers:

/**
 * 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
    }

}

希望对你有用。