Java 如何正确使用匕首2';用LibGDX进行s场注入?

Java 如何正确使用匕首2';用LibGDX进行s场注入?,java,android,dependency-injection,libgdx,dagger-2,Java,Android,Dependency Injection,Libgdx,Dagger 2,我在基于LibGDX的游戏中注入一些依赖项时遇到问题。 谁能告诉我我错过了什么 我有两个模块 首先提供Android的上下文: @Module public class AppModule { Context context; public AppModule(Context context) { this.context = context; } @Provides @Singleton Context providesCon

我在基于LibGDX的游戏中注入一些依赖项时遇到问题。 谁能告诉我我错过了什么

我有两个模块

首先提供Android的
上下文

@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);
}
现在,我添加了自定义应用程序类(在清单中定义),我在其中实例化了我的组件:

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安卓的启动器中,在
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
方法

我的
菜单屏幕
类:

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()

我是否应该在注入任何内容的每个类中使用组件的
inject()
方法(无论使用字段/构造函数注入)

我已经阅读了很多Dagger的教程和文档,但是每个可用的示例都很简单(大多数情况下,它们显示了活动中的简单注入)


经过几个小时的尝试,我决定我需要找一个在匕首方面更有经验的人。我很乐意提供任何提示和/或资源。

注释本身不会起任何作用-
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();
    }
}
如果可以提供所有依赖项,这将起作用

使用匕首意味着你不应该自己叫construcors

((GameApplication) getApplication()).getGameComponent().inject(this);

initialize(new GameName());
GameName
显然应该从
GameComponent
提供

如果可以只提供类,则不要使用模块

@Provides
@Singleton
AnalyticsUtils providesAnalyticsUtils(Context context) {
    return new AnalyticsUtils(context);
}
你不需要这些。使用
@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);
}

事实上,我的
MenuScreen
类(以及许多其他类)使用了我想要注入的更多依赖项。我想我应该用多个参数创建这样糟糕的构造函数,还是创建包含其他对象的包装类?这就是为什么我想使用字段注入的原因。@ TimMUS我会考虑“包含其他对象的包装类”作为反模式。如果一个类有太多的依赖项,这可能意味着它做的太多了。然后,你应该将它的一些特性提取到其他类中。是的,我在发表我的评论后,已经考虑过这一点。此外,感谢您的回复。我认为你的答案是正确的。它让我对这个话题有了一些了解,并改变了我对Dagger的观点和理解(尤其是依赖于缺乏模块使用要求的快捷方式)。