我在基于LibGDX的游戏中注入一些依赖项时遇到问题。 谁能指出我缺少的东西?
我有两个模块。
首先提供Android' Context
:
@Module
public class AppModule {
Context context;
public AppModule(Context context) {
this.context = context;
}
@Provides
@Singleton
Context providesContext() {
return context;
}
}
第二个提供与Google Analytics互动的课程:
@Module
public class ServicesModule {
@Provides
@Singleton
AnalyticsUtils providesAnalyticsUtils(Context context) {
return new AnalyticsUtils(context);
}
}
我的组件类以这种方式实现:
@Singleton
@Component(modules = {AppModule.class, ServicesModule.class})
public interface GameComponent {
void inject(Launcher launcher);
}
现在,我已经添加了自定义Application类(在manifest中定义),我在其中实例化了我的组件:
public class GameApplication extends Application {
private GameComponent gameComponent;
@Override
public void onCreate() {
super.onCreate();
gameComponent = DaggerGameComponent.builder()
.appModule(new AppModule(this))
.servicesModule(new ServicesModule())
.build();
}
public GameComponent getGameComponent() {
return gameComponent;
}
}
在LibGDX Android的启动器中,我在onCreate
方法中调用了组件的inject()
方法:
public class Launcher extends AndroidApplication {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((GameApplication) getApplication()).getGameComponent().inject(this);
initialize(new GameName());
}
}
让我们说GameName
是一个扩展LibGDX Game
类的类。在其create
方法中,我调用setScreen
方法启动菜单屏幕。
我的MenuScreen
课程:
public class MenuScreen extends ScreenAdapter {
@Inject AnalyticsUtils analyticsUtils;
public MenuScreen(GameName game) {
// Some initialization.
useAnalytics();
}
private void useAnalytics() {
analyticsUtils.someMethod();
}
}
如上所述,在MenuScreen
类中,我想使用字段注入注入AnalyticsUtils
类。
在构造函数中,我调用的方法是使用analyticsUtils
对象并调用它的方法。
在我正在调用的analyticsUtils.someMethod()
行,我正在NullPointerExcetion
(试图在.someMethod()
对象上调用null
)。
我是否应该在每个注入任何东西的类中使用组件的inject()
方法(无论使用字段/构造函数注入)?
我已阅读了很多Dagger的教程和文档,但每个可用的示例都很简单(大多数情况下,它们在活动中显示简单的注入)。
经过几个小时的尝试后,我决定要问一位在匕首方面经验丰富的人。我会很高兴任何提示和/或资源。
答案 0 :(得分:2)
注释本身不会做任何事情 - MenuScreen
没有提供它的依赖。
只要有可能就使用构造函数注入。
字段注入将由活动和片段使用,因为您无法修改/使用它们的构造函数。除了一些罕见的情况,你应该尽可能使用构造函数注入。
public class MenuScreen extends ScreenAdapter {
private final AnalyticsUtils analyticsUtils;
@Inject
public MenuScreen(GameName game, AnalyticsUtils analyticsUtils) {
this.analyticsUtils = analyticsUtils;
// Some initialization.
useAnalytics();
}
private void useAnalytics() {
analyticsUtils.someMethod();
}
}
如果可以提供所有依赖项,这将有效。
使用匕首意味着您不自己调用构造函数
((GameApplication) getApplication()).getGameComponent().inject(this);
initialize(new GameName());
GameName
显然应该从GameComponent
提供。
如果您可以提供课程,请不要使用模块
@Provides
@Singleton
AnalyticsUtils providesAnalyticsUtils(Context context) {
return new AnalyticsUtils(context);
}
你不需要这些。使用class AnalyticsUtils
注释@Singleton
,使用@Inject
注释其构造函数,然后可以提供。 没有任何模块。这就是构造函数注入的原因。
使用注入
您没有提供有关您在哪里做什么的背景信息。但鉴于可以提供GameName
,可以构建MenuScreen
。你可以,例如只需执行以下操作
@Inject
GameName mGame;
@Inject
MenuScreen mMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((GameApplication) getApplication()).getGameComponent().inject(this);
initialize(mGame);
}