使用Dagger 2来注入到服务中。

39

我有一个应用程序,基本上是一项服务,它一直在运行并在发生某些事情时向用户发出警报。

当服务创建警报时,它需要提供自己的context,以便在发生某些事情时,警报可以对服务进行回调

例如:

public MyService extends Service{
    private SomeAlarm alarm;

    @Override
    public void onCreate() {
        super.onCreate();
        alarm = new SomeAlarm(MyService.this);
    }
}

我该如何将SomeAlarm类注入到服务中,并将服务上下文作为变量传递给SomeAlarm?


如果使用 Hilt,则这可能是一个解决方案 https://dev59.com/7lIG5IYBdhLWcg3wmCgl - Fayaz
2个回答

50

我是凭空写出这段代码的,所以可能有一两个笔误。

你可以像向活动中注入内容时那样进行操作。

  1. 声明一个组件,
  2. 在该组件上添加inject方法,
  3. 添加提供服务的模块
  4. 创建该组件的构建器
  5. 将您的模块添加到构建器中
  6. 使用该组件注入您的服务

您的模块和组件应该长这样(也许需要添加一些范围)。

@Module
class ServiceModule {

    MyService mService;

    ServiceModule(MyService service) {
        mService = service;
    }

    @Provides
    MyService provideMyService() {
        return mService;
    }
}

@Component(modules=ServiceModule.class)
interface MyServiceComponent {
    void inject(MyService service);
}

然后在onCreate中创建您的组件并注入您的警报。

@Inject
private SomeAlarm alarm;

public void onCreate() {
    DaggerMyServiceComponent.builder()
            .serviceModule(new ServiceModule(this))
            .build()
            .inject(this);

    alarm.doStuff();
}

假设您的闹钟可以通过具有类似以下内容的@Inject注释构造函数进行构造注入:

class SomeAlarm {
    @Inject
    SomeAlarm(MyService service) {
        /*constructor stuff*/
    }
}

否则,您只需将警报创建添加到您的模块中即可。


2
谢谢你的回答。当我尝试注入警报时,代码无法编译,显示“Builder()在Builder中具有私有访问权限”。 - Ofek Agmon
这就是为什么我在我的回答中添加了第一行。它是 DaggerMyServiceComponent.builder() - David Medenjak
谢谢,我还需要在 DaggerMyServiceComponent.builder() 前面去掉 "new"。 - Ofek Agmon
1
@AdamHurwitz 我认为对大多数情况来说都不会有影响,因为服务中的 onCreate() 中没有太多事情要处理。 - David Medenjak
1
@AllDayAmazing 你想要做什么?你可以使用方法注入,它类似于字段注入,但由于框架创建服务,因此无法使用构造函数注入。除此之外,你可以随时向组件添加 provision 方法并手动获取你的依赖项,使用 Dagger 作为一种服务定位器。 - David Medenjak
显示剩余7条评论

20

我知道这个问题已经有了答案,但还有另一种方法可以解决它。

首先,使你的应用程序扩展HasServiceInjector,像这样:

public class App extends Application implements HasActivityInjector, 
HasServiceInjector {

@Inject
DispatchingAndroidInjector<Activity> dispatchingActivityInjector;
@Inject
DispatchingAndroidInjector<Service> dispatchingServiceInjector;

@Override
public void onCreate() {
    super.onCreate();
    AppInjector.init(this);
}

@Override
public AndroidInjector<Activity> activityInjector() {
    return dispatchingActivityInjector;
}

@Override
public AndroidInjector<Service> serviceInjector() {
    return dispatchingServiceInjector;
}

}

然后创建一个ServiceBuilderModule,它会对服务执行注入:

@Module
abstract class ServiceBuilderModule {

@ContributesAndroidInjector
abstract MyService contributeMyService();

}

然后将新模块注册到您的组件

@Component(modules = {
    AndroidSupportInjectionModule.class,
    AppModule.class,
    ActivityBuilderModule.class,
    ServiceBuilderModule.class
 })
 @Singleton
 public interface AppComponent {

 @Component.Builder
 interface Builder {
    @BindsInstance
    Builder application(App application);

    AppComponent build();
 }

 void inject(App app);

 }

然后覆盖您的服务的onCreate方法,并像下面的代码一样添加AndroidInjection.inject(this)

```java @Override public void onCreate() { super.onCreate(); AndroidInjection.inject(this); } ```
public class MyService extends Service {

@Override
public void onCreate() {
    AndroidInjection.inject(this);
    super.onCreate();
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

}

kotlin中的代码与上述代码完全相同。希望这能帮助一些编程人员。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接