Dagger-嵌套注入,是否有必要调用inject()? [英] Dagger - nested injections, is it necessary to call 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屋!