Skip to content

Instantly share code, notes, and snippets.

@imminent
Last active October 23, 2017 07:39
Show Gist options
  • Save imminent/5222625 to your computer and use it in GitHub Desktop.
Save imminent/5222625 to your computer and use it in GitHub Desktop.
Dagger `ObjectGraph` utility to hide the mess of injecting the different Android classes. Note this is inspired by https://github.com/pyricau/CleanAndroidCode/blob/master/cleanandroidcode/src/main/java/info/piwai/cleanandroidcode/base/GraphRetriever.java
import javax.annotation.Nonnull;
import android.app.Activity;
import android.app.Service;
import android.support.v4.app.Fragment;
import android.content.Context;
/**
* <p>Retrieves the {@link dagger.ObjectGraph} and injects dependencies.</p>
* @author Dandré Allison
*/
public final class ObjectGraph {
/**
* <p>An {@link android.app.Application} that wants to inject dependencies from an
* {@link dagger.ObjectGraph object graph} must implement {@link ObjectGraphApplication}.</p>
*/
public interface ObjectGraphApplication {
/**
* <p>Injects dependencies into the given Object.</p>
*/
@Nonnull void inject(Object dependent);
}
/**
* <p>Injects the dependencies for the given {@link Activity}.</p>
* @param activity The given activity
*/
public static void inject(@Nonnull Activity activity) {
((ObjectGraphApplication) activity.getApplication()).inject(activity);
}
/**
* <p>Injects the dependencies for the given {@link Fragment}.</p>
* @param fragment The given fragment
*/
public static void inject(@Nonnull Fragment fragment) {
final Activity activity = fragment.getActivity();
if (activity == null)
throw new IllegalStateException("Attempting to get Activity before it has been attached to "
+ fragment.getClass().getName());
((ObjectGraphApplication) activity.getApplication()).inject(fragment);
}
/**
* <p>Injects the dependencies for the given {@link Service}.</p>
* @param service The given service
*/
public static void inject(@Nonnull Service service) {
((ObjectGraphApplication) service.getApplication()).inject(service);
}
/**
* <p>Injects the dependencies for the given {@link Object} from the given {@link Context}.</p>
* @param context The given context
* @param object The given object
*/
public static void inject(@Nonnull Context context, @Nonnull Object object) {
((ObjectGraphApplication) context.getApplicationContext()).inject(object);
}
/* Private Constructor */
/** Blocks instantiation of the {@link ObjectGraph} class. */
private ObjectGraph() { }
}
@nimeacuerdo
Copy link

Not sure about this approach over the inheritance based for fragments and activitites.

Also I guess the inject(this) at line 59 is really inject(object). Nevertheless, I would provide an ObjectGraphApplication as parameter rather than a Context in that method.

@imminent
Copy link
Author

@nimeacuerdo, this approach isn't to replace inheritance based approach, but it is an inversion of the logic of how to inject the activity or fragment. You can still put inject(this) in a base class (and that's what I do).

And you don't provide ObjectGraphApplication as the parameter there, because it doesn't have to be the Application Context at that point, it could be an Activity Context for example, and this method allows you to get from any Context, back to the Application Context, which is the Application that implements ObjectGraphApplication.

P.S. thanks this -> object the way I copied it over, I managed to overlook that.

@nimeacuerdo
Copy link

I mean that will work only if the context is able to provide you an ObjectGraphApplication, which could not always be the case. That's what I meant with asking for ObjectGraphApplication, which is what the method needs, rather than a way to get there.

@imminent
Copy link
Author

imminent commented Oct 1, 2013

@nimeacuerdo it is simply a convenience method that removes the "how" from the "what". When you're in a class that has a reference to the Context and needs it dependencies injected, you will be calling (ObjectGraphApplication) context.getApplicationContext() to get to the ObjectGraphApplication, so I extracted it out into the method. The Context passed doesn't have to be an ObjectGraphApplication in the way the method is implemented, merely a Context that can get to the ObjectGraphApplication.

@austynmahoney
Copy link

I have simplified setting up the basic injection pattern in Android using a library I made called Hilt.

Now all you have to do is extend a couple classes, and set up your own modules and place them in the getActivityModules() methods in your subclass of HiltActivity and HiltApplication.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment