android - 使用 Dagger 2 的 CustomView 依赖注入(inject)(在 Activity 范围内)

标签 android dependency-injection dagger-2 dagger

我的问题类似于 this .

例如,我有一个 LiveData 实现:

public class CustomLiveData extends LiveData<SomeEvent> {

    @Inject
    public CustomLiveData(@ActivityContext Context context) {
        //....
    }

}

我想注入(inject)自定义 View :

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 类:

@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 注入(inject) MainActivity 而不是注入(inject) View ,我不会收到任何编译器投诉。 谢谢!

最佳答案

tl;dr 不要在自定义 View 对象中注入(inject)模型层依赖项

View 的子类不是 Dagger 2 注入(inject)的好目标。 View 对象是用来绘制的,而不是必须绘制的,因此得名“view”。 View 的构造函数应该明确这一点;它们被设计用于从 XML 中指定的属性中扩充 View 对象。换句话说,View 对象应该能够在 layout.xml 文件中指定,在生命周期的适当点进行膨胀,然后使用 获得findViewById(int id), Butterknife或数据绑定(bind)。这样,最好的自定义 View 对象就没有依赖关系了。

如果你想链接一个 View 和来自模型层的一些数据,标准模式是编写一个适配器,就像 RecyclerViewListView。如果这是不可能的,则使用 setter(例如,setData())比在构造函数中从模型层传递依赖关系或从 的生命周期方法之一中请求注入(inject)更可取查看

如果您使用 AndroidInjector 类将您的 LiveData 对象注入(inject)到 Activity 或 Fragment 中,则将提供正确的 Context 而您不必这样做做任何事情。这解释了您的评论“如果将 CustomLiveData 注入(inject) MainActivity 而不是注入(inject) View ,我不会收到任何编译器投诉。”

LiveData 对象注入(inject) Activity 后,使用上述方法之一(适配器或 setter )将数据与您的自定义 View 相关联。请参阅 Google Android 架构示例 here其中模型层的元素使用 Dagger 2 注入(inject),然后使用 findViewByIdsetAdapter()

ListView 关联

链接到讨论 View 对象注入(inject)的 Dagger 2 问题:

https://github.com/google/dagger/issues/720

关于android - 使用 Dagger 2 的 CustomView 依赖注入(inject)(在 Activity 范围内),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44844149/

相关文章:

android - Realm 插件 Dagger 构建失败,找不到符号类 DaggerApplicationComponent

Android : libopencv_java3. 所以在 aarch64 平台上找不到 armeabi-v7a abi 过滤器

java - 为什么 30 秒的声音在我的 LibGDX 项目中只播放 4 秒?

c# - 如何在后台任务中使用具有依赖性的作用域服务

java - 如何在 servlet(或任何其他 Java 类)中使用 @Resource 注释?

android - Dagger2 依赖组件与子组件

android - 修复了 Android 上使用 fmx 字体的 : canvas. 填充文本被 block 背景包围的问题

javascript - 如何在 android webview 中隐藏我的网站标题?

php - zf2 解析模块 View 路径

java - 如何使用 Dagger-2 延迟注入(inject)接口(interface)?