android - 您如何将由 AndroidInjector 注入的 android 对象(Service、Activity ...)重新注入其他对象?
问题描述
我有一个具有 DaggerServiceComponent 的服务,它将成功注入所有服务依赖项。
问题是我还有一个 ServiceManager 类,它需要引用 Service 才能“管理”服务任务。IE
应用
public class ApplicationBase extends Application implements HasServiceInjector {
@Inject
DispatchingAndroidInjector<Service> dispatchingAndroidServiceInjector;
protected void setupServiceComponent(Context context) {
ServiceContextModule serviceContextModule = new ServiceContextModule(context);
ServiceComponent serviceComponent = DaggerServiceComponent.builder().serviceContextModule(serviceContextModule).build();
serviceComponent.inject(this);
}
@Override
public AndroidInjector<Service> serviceInjector() {
return dispatchingAndroidServiceInjector;
}
}
零件
@Singleton
@Component(modules = { /* modules */})
public interface ServiceComponent extends AndroidInjector<ApplicationBase > {
ServiceManager provideServiceManager();
void inject(ApplicationBase appBase);
// ..
}
模块
@Module
public abstract class MediaPlaybackServiceModule {
@ContributesAndroidInjector
abstract MediaPlaybackService provideMediaPlaybackService();
}
MediaPlaybackService 我的服务
public class MediaPlaybackService extends MediaBrowserServiceCompat {
// ...
private ServiceManager serviceManager;
@Override
public void onCreate() {
init();
super.onCreate();
// ...
}
/**
* TO BE CALLED BEFORE SUPER CLASS
*/
private void init() {
AndroidInjection.inject(this);
serviceManager.setMediaPlaybackService(this);
}
//...
// declaration of other dependencies
}
如果你看看我目前在做什么,我手动添加了对 setter 方法的调用,以在成功注入的 ServiceManager 类中设置“服务”引用。
服务管理器类如下所示:
public class ServiceManager {
@Inject
public ServiceManager(MediaSessionAdapter mediaSession,
MyNotificationManager myNotificationManager) {
this.mediaSession = mediaSession;
this.notificationManager = myNotificationManager;
}
// BODY OF CLASS
public void setMediaPlaybackService(MediaPlaybackService mediaPlaybackService) {
this.service = mediaPlaybackService;
}
}
但理想情况下,我希望服务管理器构造函数看起来像
@Inject
public ServiceManager(MediaPlaybackService mediaPlaybackService, MediaSessionAdapter mediaSession,
MyNotificationManager myNotificationManager) {
this.service = mediaPlaybackService;
this.mediaSession = mediaSession;
this.notificationManager = myNotificationManager;
}
我需要对我的 dagger2 代码进行哪些更改才能实现此目的?
注意:为简单起见,我删除了应用程序中使用的额外代码,但可以在此处找到
解决方案
因此,对于所有面临与我自己类似问题的人,我已经对 dagger-android 进行了很多实验,并发现执行以下操作要简单得多:
1)使活动抽象
public abstract MainActivity extends AppCompatActivity {
...
abstract void initDependencies();
...
@Inject
public void setMyDependency(MyDependency myDependency) { ... }
}
2)创建一个子类来初始化你的依赖项,从而在你的活动中删除一个匕首依赖项
public MainActivityProduction extends MainActivity {
@Override
void initDependencies() {
DaggerMainActivityComponent.factory().create(..., this)
.inject(this);
}
@Override
public void onCreate() {
initDependencies();
super.onCreate();
}
}
请注意,这允许一个单独的组件可用于测试,如匕首文档https://dagger.dev/testing中建议的那样,即
public MainActivityTesting extends MainActivity {
@Override
void initDependencies() {
DaggerMainActivityTestingComponent.factory().create(..., this)
.inject(this);
}
@Override
public void onCreate() {
initDependencies();
super.onCreate();
}
}
3)因此,您的组件将如下所示:
@Component(modules = { /* modules */})
public interface MainActivityComponent {
...
@Component.Factory
interface Factory {
MainActivityComponent create(...,
@BindsInstance MainActivity);
}
}
这意味着您可以让任何模块引用您的 MainActivity
@Module
public class MyDependencyModule {
@Provides
public MyDependency providesMyDependency(MainActivity MainActivity) {
return new MyDependency(mainActivity);
}
}
这个解决方案:
- 将样板设置代码与主代码分离
- 允许轻松注入测试实现
- 删除对 Application 类的依赖以设置您的依赖项。
推荐阅读
- swift - 调整元素大小以适应 spritekit 中的屏幕大小
- excel - 除非特定工作表处于活动状态,否则 VBA 代码不起作用
- gemfire - Apache Geode Redis 适配器无法持久化
- python - 过滤数据框会返回“空数据框”
- java - JNDI LDAP 池连接
- flutter - 在这里将逻辑放在图标上几乎没有帮助
- javascript - window.speechSynthesis.speak(msg) 在单击按钮之前不起作用
- c# - WPF 应用程序似乎没有收到响应
- sorting - Google表格,根据单列中的唯一值对表格进行排序
- webgl - 应用置换贴图和高光贴图