Skip to content

Commit

Permalink
Add two Android examples.
Browse files Browse the repository at this point in the history
Simple example showing how to integrate Dagger and Android as well as a more complete example showing per-Activity graphs.

Since Travis CI hates Android we explicitly disable the modules being compiled in the build config.
  • Loading branch information
JakeWharton committed May 2, 2013
1 parent 5a506f1 commit d45582b
Show file tree
Hide file tree
Showing 28 changed files with 886 additions and 28 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: java
install: mvn install clean --fail-never --quiet -DskipTests=true -Dinvoker.skip=true
script: mvn verify

install: mvn install clean -P!android --fail-never --quiet -DskipTests=true -Dinvoker.skip=true
script: mvn verify -P!android

notifications:
email: false
Expand Down
21 changes: 21 additions & 0 deletions examples/android-activity-graphs/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0.0"
package="com.example.dagger.activitygraphs">

<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="17"/>

<application android:label="@string/app_name">
<activity
android:label="@string/app_name"
android:name=".ui.HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
17 changes: 17 additions & 0 deletions examples/android-activity-graphs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Example: Android Activity Graphs
================================

Building on top of the simple Android example, this example demonstrates how it is possible to
create child graphs for each activity which extend from the global graph.

Some of the advantages of the activity scope:

* Provides the ability to inject objects which require the activity to be constructed.
* Allows for the use of singletons on a per-activity basis. This is a great way to manage a
resource that is shared by a bunch of fragments in an activity.
* Keeps the global object graph clear of things that can be used only be activities.

While this example only shows the presence of an activity scope, you should be able to see the
potential for other useful scopes that can be used. For example, having a dedicated object graph
for the current user sessions is a great way to manage data that is tied to the currently logged-in
user.
63 changes: 63 additions & 0 deletions examples/android-activity-graphs/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2013 Square, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.squareup.dagger.example</groupId>
<artifactId>dagger-example-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>android-activity-graphs</artifactId>
<name>Examples: Android - Activity Graphs</name>
<packaging>apk</packaging>

<dependencies>
<dependency>
<groupId>com.squareup.dagger</groupId>
<artifactId>dagger</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>

<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>support-v4</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
</project>
4 changes: 4 additions & 0 deletions examples/android-activity-graphs/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Dagger Activity Graph</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.activitygraphs;

import android.content.Context;
import com.example.dagger.activitygraphs.ui.ActivityTitleController;
import com.example.dagger.activitygraphs.ui.HomeActivity;
import com.example.dagger.activitygraphs.ui.HomeFragment;
import dagger.Module;
import dagger.Provides;
import javax.inject.Singleton;

/**
* This module represents objects which exist only for the scope of a single activity. We can
* safely create singletons using the activity instance because ths entire object graph will only
* ever exist inside of that activity.
*/
@Module(
injects = {
HomeActivity.class,
HomeFragment.class
},
complete = false,
library = true
)
public class ActivityModule {
private final DemoBaseActivity activity;

public ActivityModule(DemoBaseActivity activity) {
this.activity = activity;
}

/**
* Allow the activity context to be injected but require that it be annotated with
* {@link ForActivity @ForActivity} to explicitly differentiate it from application context.
*/
@Provides @Singleton @ForActivity Context provideActivityContext() {
return activity;
}

@Provides @Singleton ActivityTitleController provideTitleController() {
return new ActivityTitleController(activity);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.activitygraphs;

import android.content.Context;
import android.location.LocationManager;
import dagger.Module;
import dagger.Provides;
import javax.inject.Singleton;

import static android.content.Context.LOCATION_SERVICE;

/**
* A module for Android-specific dependencies which require a {@link Context} or
* {@link android.app.Application} to create.
*/
@Module(library = true)
public class AndroidModule {
private final DemoApplication application;

public AndroidModule(DemoApplication application) {
this.application = application;
}

/**
* Allow the application context to be injected but require that it be annotated with
* {@link ForApplication @Annotation} to explicitly differentiate it from an activity context.
*/
@Provides @Singleton @ForApplication Context provideApplicationContext() {
return application;
}

@Provides @Singleton LocationManager provideLocationManager() {
return (LocationManager) application.getSystemService(LOCATION_SERVICE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.activitygraphs;

import android.app.Application;
import dagger.ObjectGraph;
import java.util.Arrays;
import java.util.List;

public class DemoApplication extends Application {
private ObjectGraph applicationGraph;

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

applicationGraph = ObjectGraph.create(getModules().toArray());
}

/**
* A list of modules to use for the application graph. Subclasses can override this method to
* provide additional modules provided they call {@code super.getModules()}.
*/
protected List<Object> getModules() {
return Arrays.<Object>asList(new AndroidModule(this));
}

ObjectGraph getApplicationGraph() {
return applicationGraph;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.activitygraphs;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import dagger.ObjectGraph;
import java.util.Arrays;
import java.util.List;

/** Base activity which sets up a per-activity object graph and performs injection. */
public abstract class DemoBaseActivity extends FragmentActivity {
private ObjectGraph activityGraph;

@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Create the activity graph by .plus-ing our modules onto the application graph.
DemoApplication application = (DemoApplication) getApplication();
activityGraph = application.getApplicationGraph().plus(getModules().toArray());

// Inject ourselves so subclasses will have dependencies fulfilled when this method returns.
activityGraph.inject(this);
}

@Override protected void onDestroy() {
// Eagerly clear the reference to the activity graph to allow it to be garbage collected as
// soon as possible.
activityGraph = null;

super.onDestroy();
}

/**
* A list of modules to use for the individual activity graph. Subclasses can override this
* method to provide additional modules provided they call and include the modules returned by
* calling {@code super.getModules()}.
*/
protected List<Object> getModules() {
return Arrays.<Object>asList(new ActivityModule(this));
}

/** Inject the supplied {@code object} using the activity-specific graph. */
public void inject(Object object) {
activityGraph.inject(object);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.activitygraphs;

import android.app.Activity;
import android.support.v4.app.Fragment;

/** Base fragment which performs injection using the activity object graph of its parent. */
public class DemoBaseFragment extends Fragment {
@Override public void onAttach(Activity activity) {
((DemoBaseActivity) activity).inject(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dagger.activitygraphs;

import java.lang.annotation.Retention;
import javax.inject.Qualifier;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Qualifier @Retention(RUNTIME)
public @interface ForActivity {
}
Loading

0 comments on commit d45582b

Please sign in to comment.