LibGDX 如何正确使用 Dagger 2 的场注入?
How to correctly use Dagger 2's field injection with LibGDX?
我在基于 LibGDX 的游戏中注入一些依赖项时遇到问题。
谁能指出我缺少的东西?
我有两个模块。
先提供Android的Context
:
@Module
public class AppModule {
Context context;
public AppModule(Context context) {
this.context = context;
}
@Provides
@Singleton
Context providesContext() {
return context;
}
}
第二个提供与 Google 分析交互的 class:
@Module
public class ServicesModule {
@Provides
@Singleton
AnalyticsUtils providesAnalyticsUtils(Context context) {
return new AnalyticsUtils(context);
}
}
我的组件class是这样实现的:
@Singleton
@Component(modules = {AppModule.class, ServicesModule.class})
public interface GameComponent {
void inject(Launcher launcher);
}
现在,我在实例化我的组件的地方添加了自定义应用程序 class(在清单中定义):
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
class 的 class。在它的 create
方法中,我调用 setScreen
方法来启动我的菜单屏幕。
我的MenuScreen
class:
public class MenuScreen extends ScreenAdapter {
@Inject AnalyticsUtils analyticsUtils;
public MenuScreen(GameName game) {
// Some initialization.
useAnalytics();
}
private void useAnalytics() {
analyticsUtils.someMethod();
}
}
如上所述,在 MenuScreen
class 中,我想使用字段注入来注入 AnalyticsUtils
class。
在构造函数中,我正在调用一个使用 analyticsUtils
对象的方法并调用它的方法。
在我调用 analyticsUtils.someMethod()
的那一行,我得到 NullPointerExcetion
(试图在 null
对象上调用 .someMethod()
)。
我是否应该在我注入任何东西的每个 class 中使用组件的 inject()
方法(无论使用字段/构造函数注入)?
我已经阅读了很多 Dagger 的教程和文档,但是每个可用的示例都很简单(大多数情况下,它们显示了活动中的简单注入)。
经过几个小时的尝试,我决定我需要请教对 Dagger 更有经验的人。如果有任何提示和/或资源,我将很高兴。
注解本身不会做任何事情——MenuScreen
没有提供它的依赖项。
尽可能使用构造函数注入。
活动和片段将使用字段注入,因为您不能 modify/use 它们的构造函数。除了一些罕见的情况,你应该尽可能使用构造函数注入。
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();
}
}
如果可以提供所有依赖项,这将起作用。
使用 dagger 意味着你应该不自己调用构造函数
((GameApplication) getApplication()).getGameComponent().inject(this);
initialize(new GameName());
GameName
应该 显然 由 GameComponent
.
提供
如果你能提供就不要使用模块 类
@Provides
@Singleton
AnalyticsUtils providesAnalyticsUtils(Context context) {
return new AnalyticsUtils(context);
}
你不需要这些。用@Singleton
注解class AnalyticsUtils
,用@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);
}
我在基于 LibGDX 的游戏中注入一些依赖项时遇到问题。 谁能指出我缺少的东西?
我有两个模块。
先提供Android的Context
:
@Module
public class AppModule {
Context context;
public AppModule(Context context) {
this.context = context;
}
@Provides
@Singleton
Context providesContext() {
return context;
}
}
第二个提供与 Google 分析交互的 class:
@Module
public class ServicesModule {
@Provides
@Singleton
AnalyticsUtils providesAnalyticsUtils(Context context) {
return new AnalyticsUtils(context);
}
}
我的组件class是这样实现的:
@Singleton
@Component(modules = {AppModule.class, ServicesModule.class})
public interface GameComponent {
void inject(Launcher launcher);
}
现在,我在实例化我的组件的地方添加了自定义应用程序 class(在清单中定义):
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
class 的 class。在它的 create
方法中,我调用 setScreen
方法来启动我的菜单屏幕。
我的MenuScreen
class:
public class MenuScreen extends ScreenAdapter {
@Inject AnalyticsUtils analyticsUtils;
public MenuScreen(GameName game) {
// Some initialization.
useAnalytics();
}
private void useAnalytics() {
analyticsUtils.someMethod();
}
}
如上所述,在 MenuScreen
class 中,我想使用字段注入来注入 AnalyticsUtils
class。
在构造函数中,我正在调用一个使用 analyticsUtils
对象的方法并调用它的方法。
在我调用 analyticsUtils.someMethod()
的那一行,我得到 NullPointerExcetion
(试图在 null
对象上调用 .someMethod()
)。
我是否应该在我注入任何东西的每个 class 中使用组件的 inject()
方法(无论使用字段/构造函数注入)?
我已经阅读了很多 Dagger 的教程和文档,但是每个可用的示例都很简单(大多数情况下,它们显示了活动中的简单注入)。
经过几个小时的尝试,我决定我需要请教对 Dagger 更有经验的人。如果有任何提示和/或资源,我将很高兴。
注解本身不会做任何事情——MenuScreen
没有提供它的依赖项。
尽可能使用构造函数注入。
活动和片段将使用字段注入,因为您不能 modify/use 它们的构造函数。除了一些罕见的情况,你应该尽可能使用构造函数注入。
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();
}
}
如果可以提供所有依赖项,这将起作用。
使用 dagger 意味着你应该不自己调用构造函数
((GameApplication) getApplication()).getGameComponent().inject(this);
initialize(new GameName());
GameName
应该 显然 由 GameComponent
.
如果你能提供就不要使用模块 类
@Provides
@Singleton
AnalyticsUtils providesAnalyticsUtils(Context context) {
return new AnalyticsUtils(context);
}
你不需要这些。用@Singleton
注解class AnalyticsUtils
,用@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);
}