1

I am getting into Inversion of Control, specifically using Guice and RoboGuice for Android and I have a question.

I have a method call that returns a Resource (which is essentially an XML or JSON String).

public Resource getResource(){
// Some implementation details that call a web service and throw the result in a string...
String resource = ........
}

The Resource class is really just a wrapped String, so I figured it made sense to pass it in in the constructor, since it is an essential part of a Resource object.

public class Resource{
   Resource(String theXMLorJSON){
   ...
   }
}

A couple of questions:

  1. How do I construct a new Resource in the getResource call? I would think that I want to use IoC and not call new in the method.
  2. If another class takes a Resource in the constructor, how can I use the Guice container to construct it when I need a dynamic String at construction time? I just asked a similar question and believe there may be a specific way to handle this using Guice.

Thanks so much!

Community
  • 1
  • 1
skaz
  • 21,962
  • 20
  • 69
  • 98

1 Answers1

2

I think you may be misunderstanding something about dependency injection. You don't need to try to avoid using new in all cases... you primarily want to avoid using new to create anything that you might want to be able to mock out for testing, and it's generally best to allow the container to wire up any class that depends on such an object.

Your Resource class, though, sounds like a simple value object that you can easily create manually in any testing you do. It also doesn't depend on any kind of services... it just contains a String. So there's no reason to try to have the container create it.

The class containing the getResource() method, on the other hand, you definitely want the container to create, because you'd like to be able to use something that depends on that class in testing without having to actually call a web service.

Note that if you have a class with a constructor that takes both dependencies you want injected by the container and parameters that are only known at runtime, you need to create an intermediate factory of some kind with a method that only takes the runtime parameters. With Guice you can automatically create such a factory from an interface using the Assisted Inject (not sure if that works with RoboGuice, but it's easy to create such a factory implementation manually too).

ColinD
  • 108,630
  • 30
  • 201
  • 202
  • Thanks a lot for the answer. I am also in Arlington, VA, btw. – skaz Nov 19 '11 at 22:26
  • A couple more questions if you don't mind. 1) Why does the example in the "Factories by Hand" section of the page you link take a `Provider` instead of just a `CreditService`? Couldn't just the `CreditService` be injected? 2) If I have another class, `ResourceUser` that takes a `Resource` in the constructor, and the `Resource` constructor takes the `String`, how do I go about setting up `ResourceUser` with Guice? Sorry if this is naive... – skaz Nov 19 '11 at 22:57
  • That's done to ensure that the factory doesn't change the scoping of the `CreditService`. For example, `CreditService` could be request-scoped in a web application, so you need to ensure you're getting the correct instance each time the factory is called. If all the dependencies are singletons, you could just inject them directly... but you shouldn't assume that in the factory. See [Injecting Providers](http://code.google.com/p/google-guice/wiki/InjectingProviders). – ColinD Nov 19 '11 at 23:02