Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding Non Activity Classes to Dagger 2 Graph Android

I'm having a hard time wrapping my head around how to use Dagger 2.0 outside of the limited examples I've seen. Let's take an example reading application. In this reading app, there is a library of a user's stories and the ability to Log in. The classes of interest for the purpose of this example are:

MainApplication.java - extends Application

LibraryManager.java - Manager which is responsible for adding/removing stories in the user's library. This is called from the MainApplication

AccountManager.java - Manager which is responsible for saving all a user's login information. It can be called from the LibraryManager

I'm still trying to wrap my head around what Components and Modules I should be creating. Here's what I can gather so far:

Create a HelperModule that provides an AccountManager and LibraryManager instance:

@Module
public class HelperModule {

    @Provides
    @Singleton
    AccountManager provideAccountManager() {
        return new AccountManager();
    }

    @Provides
    @Singleton
    LibraryManager provideLibraryManager() {
        return new LibraryManager();
    }

}

Create a MainApplicationComponent that lists the HelperModule in its list of modules:

@Singleton
@Component(modules = {AppModule.class, HelperModule.class})
public interface MainApplicationComponent {
    MainApplication injectApplication(MainApplication application);
}

Include @Injects LibraryManager libraryManager in the MainApplication and inject the application into the graph. Finally it queries the injected LibraryManager for the number of stories in the library:

public class MainApplication extends Application {

    @Inject LibraryManager libraryManager;

    @Override
    public void onCreate() {
        super.onCreate();

        component = DaggerMainApplicationComponent.builder()
                .appModule(new AppModule(this))
                .helperModule(new HelperModule())
                .build();
        component.injectApplication(this);

        // Now that we have an injected LibraryManager instance, use it
        libraryManager.getLibrary();
    }
}

Inject the AccountManager into the LibraryManager

public class LibraryManager {
    @Inject AccountManager accountManager;

    public int getNumStoriesInLibrary() {
        String username = accountManager.getLoggedInUserName();
        ...
    }
}

However the problem is that the AccountManager is null when I try to use it in the LibraryManager and I don't understand why or how to solve the problem. I'm thinking that it's because the MainApplication that was injected into the graph doesn't use the AccountManager directly, but then do I need to inject the LibraryManager into the graph some how?

like image 832
odiggity Avatar asked Dec 24 '22 20:12

odiggity


1 Answers

modify your classes as follow and it would work:

your POJO:

public class LibraryManager {
    @Inject AccountManager accountManager;

    public LibraryManager(){
        MainApplication.getComponent().inject(this);
    }

    public int getNumStoriesInLibrary() {
        String username = accountManager.getLoggedInUserName();
        ...
    }

    ...
}

your component Interface:

 @Singleton
 @Component(modules = {AppModule.class, HelperModule.class})
    public interface MainApplicationComponent {
        void inject(MainApplication application);
        void inject(LibraryManager lm);
    }
 }

your application Class :

public class MainApplication extends Application {
    private static MainApplicationComponent component;

    @Inject LibraryManager libraryManager;

    @Override
    public void onCreate() {
        super.onCreate();

        component = DaggerMainApplicationComponent.builder()
                .appModule(new AppModule(this))
                .helperModule(new HelperModule())
                .build();
        component.injectApplication(this);

        // Now that we have an injected LibraryManager instance, use it
        libraryManager.getLibrary();
    }

    public static MainApplicationComponent getComponent(){return component;}


}

In fact, you need to do the same for all of your dependent classes, basically you have access to the application class in all Activity sub-classes so making get component as an static method is none-less. but for POJO u need to catch the component somehow. there are a lot of way to implement. this is just an illustration to give u the idea how it works. now you can destroy the mars :)

like image 186
Javad Jafari Avatar answered Jan 06 '23 19:01

Javad Jafari