@Inject字段的空对象

时间:2015-03-18 22:11:33

标签: java android dependency-injection dagger-2

我正在关注我的Android应用程序的MVC模式,并且已经遇到过这个问题几次并且不得不解决它。 当我的应用程序能够使用字段上的@Inject注释创建注入对象时,该对象@Inject字段为空,通常会导致崩溃。例如,我有控制器类将处理逻辑和流动。任何片段/活动都将回调到其控制器以通知用户交互/状态更改。但是,注入的Controller实例通常为空。

我将举一个简单的例子来说明。下面,Controller正在创建一个注入活动,然后使用它通过添加片段来启动流程。处理该依赖关系但是对控制器的活动依赖性不是(即为空)。

用于处理业务逻辑和流程的Simple Controller类:

public class SomeController {
    @Inject
    SomeActivity someActivity;

    private SomeComponent component;

    private final Application app;

    @Inject
    public SomeController(Application app) {
        this.app = app;
    }

    private void startActivity() {
        component = Dagger_SomeComponent().builder()
             .someModule(app)
             .build();

        someActivity.getFragmentManager().beginTransaction().
            .add(R.id.content, SomeFragment.class, null)
            .commit();
    }

    public void activityStarted() {
        //callback when Activity is ready...
    }
}

处理用户交互并回调控制器以执行某些业务逻辑的简单活动:

public class SomeActivity extends Activity {

    @Inject
    SomeController controller;

    private void controllerCallback() {
          //notify controller of something here...
    }
}

用于将对象注入图形的简单模块类:

@Module
public class SomeModule {

    private Application app;

    public SomeModule(Application app) {
         this.app = app;
    }

    @Provides
    @Singleton
    SomeController provideSomeController( return new SomeController(app); )

    @Provides
    SomeActivity provideSomeActivity( return new SomeActivity();)
}

Simple Component类,用于提供使用对象的方法:

@Component
public interface SomeComponent {

    void addController(SomeController controller);

    SomeController controller();

    SomeActivity activity();
}

3 个答案:

答案 0 :(得分:1)

我相信你的例子中遗漏了一些东西:

1)Dagger2 Component是一些提供依赖关系的模块和一些“消耗”依赖关系的注入点之间的桥梁。您的组件应至少有一个链接模块,注释应如下所示:

@Component(modules = SomeModule.class)

2)使用'new'运算符的模块中的SomeActivity实例化没有任何意义。好的,您可以创建Activity对象,但谁将管理它的状态,调用它的生命周期方法等?如果你真的想要将现有Activity的引用作为依赖项传递 - 它是可能的,但是以不同的方式。例如,创建应用程序级模块&组件,以及单独的活动级别模块&组件,将现有的Activity引用作为模块构造函数参数传递。

3)Android框架创建活动,因此您应该在活动中使用字段注入。向您的组件添加如下行:

void inject(SomeActivity activity);

将创建组件的代码放入Activity。例如onCreate():

SomeComponent component = Dagger_SomeComponent().builder()
         .someModule(getApplication())
         .build()
         .inject(this);

4)请尽量避免@Singleton注释。首先要确保您声明的所有依赖项都已满足,并且您已经不再为null。接下来,您可以检查一些现有的Dagger2开源项目,以进行正确的范围注释。

答案 1 :(得分:1)

我遇到了这个问题,并使用this accepted answer解决了这个问题。

  

TLDR:我必须在Component中添加inject()方法才能完全正确   类型,而不仅仅是inject(SomeSuperclass foo)

基本上,我有一个需要注射的活动:

class SubActivity extends BaseActivity {
    @Inject Type someVar;

    @Override
    protected void onCreate(Bundle bundle) {
       getComponent().inject(this);
    }
}

但我的组件看起来像:

@Component
public interface MyComponent {
    void inject(BaseActivity activity); // This allows SubActivity to compile but messes up injection
}

解决方案:为确切的子类型添加注入方法:

@Component
public interface MyComponent {
    void inject(BaseActivity activity);
    void inject(SubActivity activity); //<-- This solved it
}

答案 2 :(得分:0)

在我的情况下,depends-on =“ bean1”在应用程序上下文中的property-placeholder内引起了问题。我使用@PostConstruct进行注入工作。

相关问题