Dagger-嵌套注入,是否有必要调用inject()? [英] Dagger - nested injections, is it necessary to call inject()?

查看:82
本文介绍了Dagger-嵌套注入,是否有必要调用inject()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Dagger的新手,一开始我遇到了一些问题。到目前为止,我的项目结构简单。我的注入模块:

I'm new to Dagger and at the begininig I face some issues. I have simple structure so far in my project. My injection module:

@Module(
    injects = {GameBoardFragment.class, GameManager.class},
    complete = false,
    library = true
)

public class GameObjectsProviderModule {
private final Application mApplication;

public GameObjectsProviderModule(Application application){
    this.mApplication = application;
}

@Provides
@Singleton
public GameManager provideGameManager(){
    return new GameManager();
}

@Provides
public Board getBoard(){
    return new Board();
}

@Provides @Singleton @ForApplication Context provideAppContext() {
    return mApplication;
}

我的简化自定义应用程序类如下:

My simplified custom app class looks like that:

public class MyApp extends Application {
private static ObjectGraph mApplicationGraph;

@Override public void onCreate() {
    super.onCreate();

    mApplicationGraph = ObjectGraph.create(new GameObjectsProviderModule(this));
}

public static ObjectGraph getObjectGraph(){
    return mApplicationGraph;
}
}

现在,我的片段如下所示:

And now, my fragment looks like that:

public class GameBoardFragment extends Fragment {

@Inject
GameManager mGameManager;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    MyApp.getObjectGraph().inject(this);

    View root = inflater.inflate(R.layout.fragment_game_board, container, false);
    findViews(root);
    confViews();

    return root;
}
}

最后是我的GameManager类

And finally my GameManager class

public class GameManager  {

    @Inject Board mBoard;

    public GameManager(){
        MyApp.getObjectGraph().inject(this);
    }
}

安迪,嘿!大。但是我的问题是,如果我注释掉此行,为什么它不起作用:

Andy hey, it works! Great. But my question is why it doesn't work in case I comment out this line:

MyApp.getObjectGraph().inject(this);

我们是否总是显式调用inject()函数使所有必要的注入在嵌套对象中发生?
看起来并不像咖啡壶示例所示:

Do we have always explicitly call inject() function to make all necessary injections take place event in nested objects? It looks not, as shows coffe maker example:

https://github.com/square/dagger/tree/master/examples/simple/src/main/java/coffee

为什么我必须在GameManager类中调用inject()才能使其正常工作?

Why then I have to call inject() in GameManager class to get it working?

编辑:

构造剂注入方法效果很好。

The consturctor injection approach works just fine.

但是为了将来

我注释掉了模块中的两个@Provide方法,并使GameManager看起来像这样:

I commented out both @Provide methods from module and I made my GameManager look like this:

@Singleton
public class GameManager  {

@Inject Board mBoard;

@Inject
  public GameManager(){
}
}

和董事会:

public class Board {

  @Inject
  public Board() {
  }
}

但是mBoard不会不能实例化。我会尝试更多,并且我想找出合适的解决方案。

However mBoard doesn't get instantiated. I will try more and I suppose I figure out the proper solution.

推荐答案

您应该使用构造函数注入(例如, Thermosiphon 可以) ,除非有必要,否则应避免注入电场。例如,让您的 GameManager Board 作为构造函数参数:

You should rather use constructor injection (like for example the Thermosiphon does), and avoid field injection unless necessary. For example, let your GameManager have the Board as a constructor argument:

@Singleton
public class GameManager  {

  private final Board mBoard;

  @Inject
  public GameManager(final Board board){
      mBoard = board;
  }
}

Dagger将使用此构造函数来创建 GameManager (因此在 @Inject 注释中),并注意它需要一个 Board 实例。使用 ObjectGraph ,它将首先创建一个 Board ,并使用该实例创建 GameManager 。如果您这样做,则可以删除 @Provides GameManager 方法。

Dagger will use this constructor to create an instance of the GameManager (hence the @Inject annotation), and notice it needs a Board instance. Using the ObjectGraph, it will create a Board first, and use that instance to create the GameManager. You can remove the @Provides GameManager method if you do it this way.

模块中的 @Provides Board 方法。如果在 Board 构造函数中添加 @Inject 批注,则可以从模块中删除以下提供方法:

In your case, you have a @Provides Board method in your module. If you add an @Inject annotation to your Board constructor, you can remove this provides-method from your module:

public class Board {

  @Inject
  public Board() {
  }
}






如果您不这样做不想使用构造函数注入,问题是您告诉Dagger您想自己创建 GameManager 实例(因为您有 @Provides GameManager 方法)。如果删除此方法,并让Dagger像上面那样为您创建它,但在构造函数中没有 Board 参数,则Dagger也将注意到 @Inject登上字段并注入该字段。


If you don't want to use constructor injection, the problem is that you told Dagger that you want to create your GameManager instance yourself (because you have the @Provides GameManager method). If you remove this method, and let Dagger create it for you like above but without the Board parameter in the constructor, Dagger will also notice the @Inject Board field and inject that as well.

最后一点。删除 library = true complete = false 语句!这些在此示例中根本没有必要。仅当您确实知道自己在做什么时才添加它们。如果没有它们,Dagger将创建编译时错误,以通知您某些错误。如果确实包含这些内容,则是在告诉Dagger:嘿,我知道我在做什么,不用担心,这都是正确的,而实际上却不是。

A final remark. Remove the library = true and complete = false statements! These are not necessary at all in this example. Only add them if you really know what you're doing. By not having them, Dagger will create compile-time errors to notify you that something is wrong. If you do include them, you're telling Dagger "Hey, I know what I'm doing, don't worry, it's all correct", when in fact it isn't.

编辑

Dagger1网站的报价:

A quote from the Dagger1 site:


如果您的类具有@Inject注释的字段,但没有@Inject注释的
构造函数,则Dagger将使用无参数构造函数(如果存在) 。缺少@Inject批注的
类不能由Dagger构造。

If your class has @Inject-annotated fields but no @Inject-annotated constructor, Dagger will use a no-argument constructor if it exists. Classes that lack @Inject annotations cannot be constructed by Dagger.

我不经常使用此方法,所以我可能是错的。我认为这意味着您应该从构造函数中删除 @Inject 批注,像这样:

I do not use this method very often, so I could be wrong. I think this means that you should remove the @Inject annotation from your constructor, like so:

@Singleton
public class GameManager  {

  @Inject Board mBoard;

  public GameManager(){ // Or remove the constructor entirely since it's empty
  }
}

由于在 Board 字段上有 @Inject 注释, Dagger会知道使用无参数构造函数。

Since there is an @Inject annotation on the Board field, Dagger will know to use the no-argument constructor.

这篇关于Dagger-嵌套注入,是否有必要调用inject()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆