【问题标题】:View dependency injection with dagger 2使用 Dagger 2 查看依赖注入
【发布时间】:2016-07-11 05:04:01
【问题描述】:

我有一个扩展 TextView 的自定义视图。我应该在哪里调用我的组件来注入视图?

component.inject(customTextView);

【问题讨论】:

    标签: java android view dependency-injection dagger-2


    【解决方案1】:

    所以,我发现我需要在自定义视图的构造函数中添加注入(在所有视图中,或者一个调用另一个)

    例子:

    public class CustomTextView extends TextView {
       @Inject
       AnyProvider anyProvider;
    
       public CustomTextView(Context context) { this(context, null); }
       public CustomTextView(Context AttributeSet attrs) { 
          super(context, attrs);
          Application.getComponent(context).inject(this);
       }
    }
    

    【讨论】:

    • 你使用的是 dagger 2.11 吗?你能告诉我谁得到这个:Application.getComponent(context)?不能让我的应用程序返回除 AndroidInjector 之外的任何内容。谢谢。
    • 您的ApplicationComponent - 由applicationInjector() 返回 - 应该扩展AndroidInjector<MyApplication>,因此可以转换为ApplicationComponent。我收到一个编译器警告,告诉我重写 ApplicationComponent.Builder.build() 的返回类型以澄清这一点。多次调用applicationInjector() 可能不太好,因为它会多次创建组件,所以我正在存储对它的引用……但不确定这是否是最佳实践。也许跟进一个新问题。
    • @GuilhE ... 使用它,这会返回 dagger 组件 daggerAppComponent = DaggerAppComponent.builder().application(this).build();
    【解决方案2】:

    我对这种事情的一般解决方案是这样的

    public class WelcomeView
            extends LinearLayout {
        private static final String TAG = "WelcomeView";
    
        public WelcomeView(Context context) {
            super(context);
            init(context);
        }
    
        public WelcomeView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        public WelcomeView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
    
        @TargetApi(21)
        public WelcomeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            init(context);
        }
    
        private void init(Context context) {
            if(!isInEditMode()) {
                Application.getComponent(context).inject(this);
            }
        }
    

    【讨论】:

    • 你可以使用 this() 让一个构造函数调用另一个构造函数,所以你不需要在所有构造函数中添加 init
    • 是的,但我想确保从我的所有构造函数中调用它,以防 Android 做一些奇怪的事情:)
    • 摆脱静态方法不是依赖注入的重点之一吗?但是您仍然在这里调用静态方法。在活动和片段中,我知道如何避免它,但视图呢?
    • 如果你愿意也可以((CustomApplication)(context.getApplicationContext()).getComponent().inject(this);
    • @kingston 我想问题是你从哪里获得Component。我见过像单例枚举、全局 LinkedHashMap、MortarScope、自定义 ContextWrapper 等解决方案。
    【解决方案3】:

    更新:自 2.10 版本的 Dagger 起,此答案无效。

    自定义视图:

    public class CustomView extends View {
        @Inject
        AnyObject anyObject;
    
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            MainActivity mainActivity = (MainActivity) getContext();
            mainActivity.getComponent().inject(CustomView.this);
        }
    }
    

    活动:

    ActivityComponent mComponent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mComponent = DaggerActivityComponent.builder()
                        .appComponent(getApp().getAppComponent())
                        .activityModule(new ActivityModule(MainActivity.this))
                        .build();
        mComponent.inject(MainActivity.this);
        ...
    }
    
    public ActivityComponent getComponent() {
        return mComponent;
    }
    

    具有 Activity 范围的 Dagger2 组件:

    @ActivityScope
    @Component(dependencies = AppComponent.class, modules = {ActivityModule.class})
    public interface ActivityComponent extends AppComponent {
    
        void inject(MainActivity mainActivity);
        void inject(CustomView customView);
    }
    

    范围:

    @Scope
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ActivityScope {}
    

    【讨论】:

    • .activityModule(new ActivityModule(MainActivity.this)) this is deprecated now.
    • @TusharPandey 是的,它从 Dagger2 的 2.10 版本开始就被弃用了。我需要尽快更新我的答案。
    • 如果以编程方式实例化自定义视图,则不会调用 onFinishInflate(...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    相关资源
    最近更新 更多