Search code examples
androiddependency-injectionguiceroboguice

Roboguice injecting system service


I am learning to use Roboguice and I'm having som trouble understanding how to inject a system service. All the examples I've seen is injecting into an activity but I want to inject it into a POJO. I'm using Roboguice 2.0 beta 3

I have a PhoneNumber class and would like to inject the TelephonyManager service.

public class PhoneNumber {
    @Inject TelephonyManager mTelephonyManager;

    protected Integer getNetworkCountryPrefix() {

        // This gives a null pointer exception 
        mTelephonyManager.getNetworkCountryIso();
    }
}

When injecting into a class that extends RoboActivity, everything works fine. But is it possible to inject the TelephonyManager in a class that doesn't extend RoboActivity?


Solution

  • Yes, there are three main ways to get injection in your objects when using RoboGuice.

    1. Call RoboGuice.injectMembers() yourself for the object you want injection to be performed on. For most POJOs this would likely be done in the object's constructor, but could also be done at other times. Note that this is a perfectly solution but is probably the least desirable of the options as it hardcodes a dependency on your DI framework (RoboGuice).

    2. Inject into a class that already does #1 for you. You're already familiar with this method... this is exactly what RoboActivity does. Basically, most of what RoboActivity does is just call RoboGuice.injectMembers for you.

    3. Inject TelephonyManager into a class that was itself injected. This is usually the most desirable, although in your particular case it may not be desirable. Let me explain this below:

      class MyActivity extends RoboActivity {
          @Inject PhoneNumber phone;
      
          ...
      }
      
      class PhoneNumber {
          @Inject TelephonyManager tm;
      }
      

      Basically, RoboGuice just needs a chance to perform injection on your instance. For normal POJOs that are not created by RoboGuice, there's no opportunity for RoboGuice to work its magic unless you call injectMembers directly, hence solution #1. However, if you allow RoboGuice to instantiate an object for you, eg. by injecting it, then RoboGuice has control over the creation of the object and can do injection for you in that object. Thus, in the example above, when RoboGuice creates a new PhoneNumber and puts it in the phone variable, RoboGuice will perform injection on the instance and tm will be injected properly. Obviously, if you construct PhoneNumber using the new() operator instead of letting RoboGuice do it, RoboGuice won't have an opportunity to perform injection and tm will be null.

    If #3 works for you, then I would go for it. It's the most flexible way to do things, and it encourages good practices by letting the DI framework instantiate your objects for you.

    However, if a PhoneNumber is not something that you typically let RoboGuice instantiate for you, then you may want to consider going with option #1.