Android 使用dagger 2的CustomView依赖项注入(在活动范围内)
我的问题类似于 例如,我有一个Android 使用dagger 2的CustomView依赖项注入(在活动范围内),android,dependency-injection,dagger-2,dagger,Android,Dependency Injection,Dagger 2,Dagger,我的问题类似于 例如,我有一个LiveData实现: public class CustomLiveData extends LiveData<SomeEvent> { @Inject public CustomLiveData(@ActivityContext Context context) { //.... } } 公共类CustomLiveData扩展了LiveData{ @注入 公共CustomLiveData(@Activit
LiveData
实现:
public class CustomLiveData extends LiveData<SomeEvent> {
@Inject
public CustomLiveData(@ActivityContext Context context) {
//....
}
}
公共类CustomLiveData扩展了LiveData{
@注入
公共CustomLiveData(@ActivityContext上下文){
//....
}
}
我要将其注入到自定义视图中:
public class CustomView extends View {
@Inject
SomeApplicationProvider anyProvider;
@Inject
CustomLiveData dataProvider;
// Getting @com.di.qualifiers.ActivityContext android.content.Context cannot be provided without an @Provides-annotated method.
// @com.di.qualifiers.ActivityContext android.content.Context is injected at com.repositories.CustomLiveData.<init>(context)
// com.repositories.CustomLiveData is injected at com.ui.CustomView.dataProvider com.ui.CustomView is injected at
// com.di.ApplicationComponent.inject(view)
public CustomView(Context context) { this(context, null); }
public CustomView(Context AttributeSet attrs) {
super(context, attrs);
// Works ok for application provider
Application.getComponent(context).inject(this);
}
}
公共类CustomView扩展了视图{
@注入
SomeApplicationProviderAnyProvider;
@注入
CustomLiveData数据提供者;
//如果没有@Provides注释方法,则无法提供get@com.di.qualifiers.ActivityContext android.content.Context。
//@com.di.qualifiers.ActivityContext android.content.Context被注入com.repositories.CustomLiveData。(上下文)
//com.repositories.CustomLiveData在com.ui.CustomView.dataProvider com.ui.CustomView在
//com.di.ApplicationComponent.inject(视图)
公共自定义视图(上下文){this(上下文,null);}
公共自定义视图(上下文属性集属性){
超级(上下文,attrs);
//适用于应用程序提供商
Application.getComponent(context.inject)(this);
}
}
下面是其他DI类:
@ApplicationScope
@Component(
modules = {AndroidInjectionModule.class,
ActivityBuilder.class
})
public interface ApplicationComponent extends AndroidInjector<MyApp> {
void inject(MyApp application);
void inject(CustomView view);
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<MyApp> {
public abstract ApplicationComponent build();
}
}
@ActivityScope
@Module (subcomponents = MainActivitySubcomponent.class)
public abstract class ActivityBuilder {
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity>
bindActivityInjectorFactory(MainActivitySubcomponent.Builder builder);
//...
}
@Subcomponent(modules = {MainActivityModule.class})
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity> {
}
}
@ActivityScope
@Module
public class MainActivityModule {
@Provides
@ActivityContext
public Context provideActivityContext(MainActivity activity) {
return activity;
}
// Seems to be wrong or not enough!?
@Provides
public CustomLiveData provideCustomLiveData(@ActivityContext Context context) {
return new CustomLiveData(context);
}
}
@Qualifier
public @interface ActivityContext{
}
@ApplicationScope
@组成部分(
modules={AndroidInjectionModule.class,
ActivityBuilder.class
})
公共接口应用程序组件扩展了AndroidJector{
无效注入(MyApp应用程序);
无效注入(自定义视图);
@组件生成器
抽象类生成器扩展了Androidjector.Builder{
公共抽象应用程序组件构建();
}
}
@活动范围
@模块(子组件=MainActivitySubcomponent.class)
公共抽象类ActivityBuilder{
@束缚
@英托马普
@ActivityKey(MainActivity.class)
abstract AndroidJector.Factory您的匕首层次结构如下所示:
appcomponent
->activitycomponent
您尝试在视图内部注入活动context
,该视图直接依赖于appcomponent
这是不可能的,因为没有方法可以在appcomponent
中提供活动上下文。相反,在视图内部,您应该检索活动(例如使用getContext
),从中提取activitycomponent
,然后注入CustomLiveData
tl;dr不在自定义视图
对象中注入模型层依赖项
View
的子类不是匕首2注射的好目标。View
对象是要绘制的,而不是必须绘制的,因此命名为“View”。的构造函数应该明确这一点;它们设计用于从XML中指定的属性膨胀视图
对象。换句话说,视图
对象应该能够在layout.XML
文件中指定,在生命周期中的适当点膨胀,然后使用findViewById获得(int id)
或数据绑定。这样,最好的自定义视图
对象就不需要依赖项
如果要链接视图
和模型层中的一些数据,标准模式是编写一个适配器,类似于RecyclerView
和ListView
的适配器。如果不可能,请使用setter(例如,setData()
)最好是从构造函数中的模型层传递依赖项,或者从视图的生命周期方法之一请求注入
相反,如果您使用androidjector
类将LiveData
对象注入到活动或片段中,则无需执行任何操作即可提供正确的上下文。这解释了您的注释“如果将CustomLiveData注入MainActivity而不是视图中,我不会收到任何编译器投诉。”
将LiveData
对象注入活动后,使用上述方法之一(适配器或setter)要将数据与自定义的视图关联,请参见Google Android架构示例,其中使用Dagger 2注入模型层的元素,然后使用findViewById
和setAdapter()与列表视图关联
链接到Dagger 2问题,其中讨论了视图
对象的注入:
将CustomLiveData
注入Custom
视图时,您是否遇到编译错误?请将其与您的问题一起发布。该消息包含在CustomView部分。请参阅“//Getting@com.di.qualifiers.ActivityContext android.content.Context无法…”。。。。。"你可以发布@ActivityContext
?我正在构建AR视图,它需要一个类,该类需要处理传感器值、计算和过滤的类,还需要一个类来获取位置。我不应该将这些类注入到扩展View或SurfaceView等的类中吗?@Thracian我仍然认为你应该尝试编写一个适配器,如果需要的话可能我不将传感器值或位置值显示为列表。传感器和位置输出是将地图上的兴趣点位置转换为屏幕所必需的。视图使用具有上下文和属性的构造函数。我想知道是否应该进行方法注入以注入传感器和位置管理器类。我还需要位置和传感器值如果视图不是匕首的好目标,那么匕首就不是注射的好工具。因为目标应该是独立的,并且在任何地方注射任何东西都没有特殊的限制。