PageRenderTime 1260ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/roboguice/src/main/java/roboguice/RoboGuice.java

https://code.google.com/p/roboguice/
Java | 217 lines | 130 code | 40 blank | 47 comment | 10 complexity | 788a68108b53d4fed0681e6623706b23 MD5 | raw file
  1. package roboguice;
  2. import roboguice.config.DefaultRoboModule;
  3. import roboguice.event.EventManager;
  4. import roboguice.inject.*;
  5. import android.app.Application;
  6. import android.content.Context;
  7. import com.google.inject.Guice;
  8. import com.google.inject.Injector;
  9. import com.google.inject.Module;
  10. import com.google.inject.Stage;
  11. import com.google.inject.spi.DefaultElementVisitor;
  12. import com.google.inject.spi.Element;
  13. import com.google.inject.spi.Elements;
  14. import com.google.inject.spi.StaticInjectionRequest;
  15. import java.util.ArrayList;
  16. import java.util.WeakHashMap;
  17. /**
  18. *
  19. * Manages injectors for RoboGuice applications.
  20. *
  21. * There are two types of injectors:
  22. *
  23. * 1. The base application injector, which is not typically used directly by the user.
  24. * 2. The ContextScopedInjector, which is obtained by calling {@link #getInjector(android.content.Context)}, and knows about
  25. * your current context, whether it's an activity, service, or something else.
  26. *
  27. * BUG hashmap should also key off of stage and modules list
  28. */
  29. @SuppressWarnings({"ALL"})
  30. public class RoboGuice {
  31. public static Stage DEFAULT_STAGE = Stage.PRODUCTION;
  32. protected static WeakHashMap<Application,Injector> injectors = new WeakHashMap<Application,Injector>();
  33. protected static WeakHashMap<Application,ResourceListener> resourceListeners = new WeakHashMap<Application, ResourceListener>();
  34. protected static WeakHashMap<Application,ViewListener> viewListeners = new WeakHashMap<Application, ViewListener>();
  35. protected static int modulesResourceId = 0;
  36. private RoboGuice() {
  37. }
  38. /**
  39. * Return the cached Injector instance for this application, or create a new one if necessary.
  40. */
  41. public static Injector getBaseApplicationInjector(Application application) {
  42. Injector rtrn = injectors.get(application);
  43. if( rtrn!=null )
  44. return rtrn;
  45. synchronized (RoboGuice.class) {
  46. rtrn = injectors.get(application);
  47. if( rtrn!=null )
  48. return rtrn;
  49. return setBaseApplicationInjector(application, DEFAULT_STAGE);
  50. }
  51. }
  52. /**
  53. * Return the cached Injector instance for this application, or create a new one if necessary.
  54. * If specifying your own modules, you must include a DefaultRoboModule for most things to work properly.
  55. * Do something like the following:
  56. *
  57. * RoboGuice.setAppliationInjector( app, RoboGuice.DEFAULT_STAGE, Modules.override(RoboGuice.newDefaultRoboModule(app)).with(new MyModule() );
  58. *
  59. * @see com.google.inject.util.Modules#override(com.google.inject.Module...)
  60. * @see roboguice.RoboGuice#setBaseApplicationInjector(android.app.Application, com.google.inject.Stage, com.google.inject.Module...)
  61. * @see roboguice.RoboGuice#newDefaultRoboModule(android.app.Application)
  62. * @see roboguice.RoboGuice#DEFAULT_STAGE
  63. *
  64. * If using this method with test cases, be sure to call {@link roboguice.RoboGuice.util#reset()} in your test teardown methods
  65. * to avoid polluting our other tests with your custom injector. Don't do this in your real application though.
  66. *
  67. */
  68. public static Injector setBaseApplicationInjector(final Application application, Stage stage, Module... modules) {
  69. // Do a little rewriting on the modules first to
  70. // add static resource injection
  71. for(Element element : Elements.getElements(modules)) {
  72. element.acceptVisitor(new DefaultElementVisitor<Void>() {
  73. @Override
  74. public Void visit(StaticInjectionRequest element) {
  75. getResourceListener(application).requestStaticInjection(element.getType());
  76. return null;
  77. }
  78. });
  79. }
  80. synchronized (RoboGuice.class) {
  81. final Injector rtrn = Guice.createInjector(stage, modules);
  82. injectors.put(application,rtrn);
  83. return rtrn;
  84. }
  85. }
  86. /**
  87. * Allows the user to override the "roboguice_modules" resource name with some other identifier.
  88. * This is a static value.
  89. */
  90. public static void setModulesResourceId(int modulesResourceId) {
  91. RoboGuice.modulesResourceId = modulesResourceId;
  92. }
  93. /**
  94. * Return the cached Injector instance for this application, or create a new one if necessary.
  95. */
  96. public static Injector setBaseApplicationInjector(Application application, Stage stage) {
  97. synchronized (RoboGuice.class) {
  98. int id = modulesResourceId;
  99. if (id == 0)
  100. id = application.getResources().getIdentifier("roboguice_modules", "array", application.getPackageName());
  101. final String[] moduleNames = id>0 ? application.getResources().getStringArray(id) : new String[]{};
  102. final ArrayList<Module> modules = new ArrayList<Module>();
  103. final DefaultRoboModule defaultRoboModule = newDefaultRoboModule(application);
  104. modules.add(defaultRoboModule);
  105. try {
  106. for (String name : moduleNames) {
  107. final Class<? extends Module> clazz = Class.forName(name).asSubclass(Module.class);
  108. try {
  109. modules.add(clazz.getDeclaredConstructor(Context.class).newInstance(application));
  110. } catch( NoSuchMethodException ignored ) {
  111. modules.add( clazz.newInstance() );
  112. }
  113. }
  114. } catch (Exception e) {
  115. throw new RuntimeException(e);
  116. }
  117. final Injector rtrn = setBaseApplicationInjector(application, stage, modules.toArray(new Module[modules.size()]));
  118. injectors.put(application,rtrn);
  119. return rtrn;
  120. }
  121. }
  122. public static RoboInjector getInjector(Context context) {
  123. final Application application = (Application)context.getApplicationContext();
  124. return new ContextScopedRoboInjector(context, getBaseApplicationInjector(application), getViewListener(application));
  125. }
  126. /**
  127. * A shortcut for RoboGuice.getInjector(context).injectMembers(o);
  128. */
  129. public static <T> T injectMembers( Context context, T t ) {
  130. getInjector(context).injectMembers(t);
  131. return t;
  132. }
  133. public static DefaultRoboModule newDefaultRoboModule(final Application application) {
  134. return new DefaultRoboModule(application, new ContextScope(application), getViewListener(application), getResourceListener(application));
  135. }
  136. protected static ResourceListener getResourceListener( Application application ) {
  137. ResourceListener resourceListener = resourceListeners.get(application);
  138. if( resourceListener==null ) {
  139. synchronized (RoboGuice.class) {
  140. if( resourceListener==null ) {
  141. resourceListener = new ResourceListener(application);
  142. resourceListeners.put(application,resourceListener);
  143. }
  144. }
  145. }
  146. return resourceListener;
  147. }
  148. protected static ViewListener getViewListener( final Application application ) {
  149. ViewListener viewListener = viewListeners.get(application);
  150. if( viewListener==null ) {
  151. synchronized (RoboGuice.class) {
  152. if( viewListener==null ) {
  153. viewListener = new ViewListener();
  154. viewListeners.put(application,viewListener);
  155. }
  156. }
  157. }
  158. return viewListener;
  159. }
  160. public static void destroyInjector(Context context) {
  161. final RoboInjector injector = getInjector(context);
  162. injector.getInstance(EventManager.class).destroy();
  163. injectors.remove(context);
  164. }
  165. public static class util {
  166. private util() {}
  167. /**
  168. * This method is provided to reset RoboGuice in testcases.
  169. * It should not be called in a real application.
  170. */
  171. public static void reset() {
  172. injectors.clear();
  173. resourceListeners.clear();
  174. viewListeners.clear();
  175. }
  176. }
  177. }