带匕首2的CustomView依赖项注入(在活动范围内) [英] CustomView dependency injection with dagger 2 (within activity scope)
问题描述
我的问题类似于此。
例如,我有一个 LiveData
实现:
public class CustomLiveData extends LiveData<SomeEvent> {
@Inject
public CustomLiveData(@ActivityContext Context context) {
//....
}
}
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);
}
}
以下是DI类的其余部分:
And here is the rest of DI classes:
@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{
}
注意,如果将 CustomLiveData
注入到<$ c $中,我不会收到任何编译器投诉。 c> MainActivity 代替进入视图。
谢谢!
Note, that I don't get any compiler complaints if CustomLiveData
is injected into MainActivity
instead into the view.
Thanks!
推荐答案
tl; dr不要在自定义 View内注入模型层依赖项
对象
View
的子类不是Dagger 2注入的良好目标。 View
对象用于绘制而不是必须绘制,因此名称为 view。 View
应该明确这一点;它们旨在从XML中指定的属性中扩展 View
对象。换句话说,应该能够在 layout.xml
文件中指定一个 View
对象,并在适当的位置进行充气指向生命周期,然后使用 findViewById(int id)
, Butterknife 或数据绑定。这样,最好的自定义 View
对象就没有依赖性。
tl;dr Don't inject model layer dependencies inside custom View
objects
Subclasses of View
are not good targets for Dagger 2 injection. View
objects are meant to be drawn and not must else, hence the name "view". The constructors for View
should make this clear; they are designed for inflating View
objects from attributes specified in XML. In other words, a View
object should be able to be specified in a layout.xml
file, inflated at the appropriate point in the lifecycle, and then obtained using findViewById(int id)
, Butterknife or data binding. In this way, the best custom View
objects take no dependencies.
如果要链接 View
和模型层中的一些数据,标准模式是编写类似于 RecyclerView
和 ListView 的适配器code>。如果这不可能,则使用setter(例如,
setData()
)比在构造函数中传递模型层的依赖项或从生命周期之一中请求注入更可取。 View
的方法。
If you want to link a View
and some data from the model layer, the standard pattern is to write an Adapter like those for RecyclerView
and ListView
. If this is not possible, using a setter (e.g., setData()
) is preferable to passing dependencies from the model layer in the constructor or requesting injection from within one of the lifecycle methods of the View
.
如果相反,您将 LiveData
对象注入其中使用 AndroidInjector
类的活动或片段,将提供正确的 Context
,而您无需执行任何操作。这解释了您的评论如果将CustomLiveData注入MainActivity而不是视图中,我不会收到任何编译器投诉。
If instead you inject your LiveData
object inside an Activity or Fragment using the AndroidInjector
class the correct Context
will be provided without you having to do anything. This explains your comment "I don't get any compiler complaints if CustomLiveData is injected into MainActivity instead into the view."
一旦注入了 LiveData,
对象放入活动中,请使用上述方法之一(适配器或设置器)将数据与您的自定义 View
关联。请参阅Google Android体系结构示例此处使用Dagger 2注入模型层中的元素,然后将其与 ListView $ c $相关联c>使用
findViewById
和 setAdapter()
Once you have injected the LiveData
object into the Activity, use one of the above methods (an adapter or a setter) to associate the data with your custom View
. See the Google Android Architecture example here where elements from the model layer are injected using Dagger 2 and then associated with a ListView
using findViewById
and setAdapter()
链接到Dagger 2讨论了注入 View
对象的问题:
Link to the Dagger 2 issue where injection of View
objects is discussed:
https://github.com/google/dagger/issues/720
这篇关于带匕首2的CustomView依赖项注入(在活动范围内)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!