Coder2000
Coder2000

Reputation: 281

Injecting field into module using dagger

I am trying to inject my android context from one module into another. This is my code so far:

UserProfileModule.java

@Module(
        library = true
)
public class UserProfileModule {

    @Inject Context _context;

    @Provides
    public AccountUtils.UserProfile provideUserProfile() {
        return AccountUtils.getUserProfile(_context);
    }
}

RootModule.java

@Module(
        injects = {
                PizzaApplication.class,
                UserProfileModule.class,
                MainActivity.class
        },
        includes = {
                UserProfileModule.class
        },
        library = true
)

public class RootModule {
    private final Context _context;

    public RootModule(Context context) {
        _context = context;
    }

    @Provides
    @Singleton
    public Context provideApplicationContext() {
        return _context;
    }
}

Anytime it tries to get the user profile it fails saying the object is null.]

EDIT:

PizzaApplication.java

public class PizzaApplication extends Application {
    private ObjectGraph objectGraph;

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

    private void injectDependencies() {
        objectGraph = ObjectGraph.create(new RootModule(this));
        objectGraph.inject(this);
    }

    public void inject(Object object) {
        objectGraph.inject(object);
    }
}

MainActivity.java

public class MainActivity extends BaseActivity {

    @InjectView(R.id.toolbar) public Toolbar _toolbar;
    @InjectView(R.id.drawer) public DrawerFrameLayout _drawer;
    @Inject public AccountUtils.UserProfile _profile;
    @Inject public Context _context;

    // private NavigationDrawerFragment navigationDrawerFragment;

    @Override
    protected void onCreate(Bundle saveInstanceState) {

Upvotes: 4

Views: 6871

Answers (2)

G. Lombard
G. Lombard

Reputation: 3679

tl;dr (Short version):

  1. For a minimal working example of your code, see my code on GitHub
  2. You don't need to / should't inject the Context from one module into another.
  3. The order/direction of your module includes is reversed, the UserProfileModule should include the RootModule.

More details and comments on your code:

  1. You don't need to inject something into a module, a module only provides dependencies. In your case simply making use of the module includes gives the functionality you want.
  2. Remove the library = true from UserProfileModule, because you only need this when the module's providers aren't all used directly by the classes specified in the injects list.
  3. As Niek Haarman said, you need to pass both RootModule and UserProfileModule instances to ObjectGraph.create in your PizzaApplication's onCreate.
  4. You're doing inject(this) in PizzaApplication but it's got no dependencies, so the inject isn't necessary. Based on the sample code you've provided, this makes me think you're assuming that injecting on the Application-level will also inject Activity dependencies...? You need to do the inject on your Activity too.
  5. You don't show if you're doing an inject in your Activity's onCreate -- that's most likely what's missing.
  6. You're injecting Context into the Activity but that's not necessary since you can just use getApplicationContext() in the Activity.

Here's the working code:

RootModule:

@Module(
    injects = {MainActivity.class},
    library = true,
    complete = false
)
public class RootModule {
  private final Context _context;

  public RootModule(Context context) {
    _context = context;
  }

  @Provides
  @Singleton
  public Context provideApplicationContext() {
    return _context;
  }
}

UserProfileModule:

@Module(includes = {RootModule.class})
public class UserProfileModule {
  @Provides
  public AccountUtils.UserProfile provideUserProfile(Context context) {
    return AccountUtils.getUserProfile(context);
  }
}

MainActivity:

public class MainActivity extends BaseActivity {

  @Inject
  public AccountUtils.UserProfile _profile;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ((PizzaApplication) getApplication()).inject(this);
    _profile.message();
  }

PizzaApplication:

public class PizzaApplication extends Application {
  private ObjectGraph objectGraph;

  @Override
  public void onCreate() {
    super.onCreate();
    objectGraph = ObjectGraph.create(new RootModule(this), new UserProfileModule());
  }

  public void inject(Object object) {
    objectGraph.inject(object);
  }
}

Upvotes: 6

nhaarman
nhaarman

Reputation: 100388

You have

objectGraph = ObjectGraph.create(new RootModule(this));

But, includes = { UserProfileModule.class } is no magic. You have to create it yourself:

objectGraph = ObjectGraph.create(new RootModule(this), new UserProfileModule() );

Furthermore, the @Inject annotation on the Context doesn't work. You're better off modifying your provider method:

@Provides 
public AccountUtils.UserProfile provideUserProfile(Context context) { 
    return AccountUtils.getUserProfile(context);
}

I cannot guarantee this will solve all your problems, but it will help you in the right direction.

Upvotes: 0

Related Questions