How to correctly use Dagger 2's field injection with LibGDX?

Viewed 1672

I have a problem with injecting some dependencies in my LibGDX-based game. Can anyone point me what I am missing?

I have two modules.

First provides Android's Context:

@Module
public class AppModule {
    Context context;

    public AppModule(Context context) {
        this.context = context;
    }

    @Provides
    @Singleton
    Context providesContext() {
        return context;
    }
} 

Second provides class that interacts with Google Analytics:

@Module
public class ServicesModule {
    @Provides
    @Singleton
    AnalyticsUtils providesAnalyticsUtils(Context context) {
        return new AnalyticsUtils(context);
    }
}

My component class is implemented this way:

@Singleton
@Component(modules = {AppModule.class, ServicesModule.class})
public interface GameComponent {
    void inject(Launcher launcher);
}

Now, I have added custom Application class (defined in manifest) where I have instantiated my component:

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;
    }
}

In LibGDX Android's launcher, in onCreate method I am calling component's inject() method:

public class Launcher extends AndroidApplication {

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

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

        initialize(new GameName());
    }
}

Let's say GameName is a class that extends LibGDX's Game class. In it's create method I am calling setScreen method that starts my menu screen.

My MenuScreen class:

public class MenuScreen extends ScreenAdapter {
    @Inject AnalyticsUtils analyticsUtils;

    public MenuScreen(GameName game) {
        // Some initialization.
        useAnalytics();
    }

    private void useAnalytics() {
        analyticsUtils.someMethod();
    }
}

As presented above, in MenuScreen class I want to inject AnalyticsUtils class using field injection.

In constructor I am calling a method that uses analyticsUtils object and calls it's method.

At the line, where I am calling analyticsUtils.someMethod() I am getting and NullPointerExcetion (trying to call .someMethod() on a null object).

Should I use component's inject() method in every single class in which I am injecting anything (no matter using field / constructor injection)?

I have read a lot of Dagger's tutorials and docs, but every of available examples are simple (mostly, they show simple injections in activities).

After few hours of trying I have decided I need to ask someone who is more experienced in Dagger. I will be glad for any hints and / or resources.

1 Answers
Related