Dependency Injection for Android Development: An Introduction

Adi Rosenblum Development Technologies, Java, Mobile, Tutorial 6 Comments

Attention: The following article was published over 12 years ago, and the information provided may be aged or outdated. Please keep that in mind as you read the post.

Overview

For many years now, Object Oriented developers have relied on various Dependency Injection frameworks while developing anything form desktop to web applications. For both Java and .NET developers, the ever-popular Spring Framework has become a gold standard for IT shops regardless of their size (from small entrepreneurial companies up to large enterprise Fortune 500-sized companies).

If you wish to understand more about the basics of Dependency Injection Frameworks (or Inversion of Control patterns), there are many excellent overviews already written on the web.  This article assumes you have some familiarity with the concepts and are interested in applying those patterns in an Android based development effort.  Below are just a few articles for more information:

Like most developers, I tend to rely on the tools that I’ve used before and are comfortable with.  My familiarity with these individual pieces not only allows me to develop code faster, but it also allows me to focus on the business problems at hand and not how to use the tools.   This makes me more effective and efficient at my job.

So when I started working on mobile development applications, I immediately started by setting up my typical workspace/environment.  Usually, that consists of:

  • Programming Language (Java)
  • An IDE (Eclipse)
  • A relational Database (MySql or Postgresql)
  • O/R Mapping (Hibernate)
  • Database Connection pooling (C3PO)
  • A Dependency Injection Framework (Spring)

That last piece is what puzzled me. Spring has a Mobile version as well as an Android specific implementation, but both of these felt a bit “heavy” to me.  I wanted something simpler for the apps I was working on.  A colleague of mine told me to check out Google Guice and more specifically the RoboGuice framework.

Google Guice is a lightweight injection framework that alleviates the need for the common Factory Patterns many developers turn to when needing to marshal the creation of objects. RoboGuice is an extension of that framework built specifically for Android to help developers cover typical tasks in Android development. There are also other frameworks available, so check out the post by Keyhole’s Shannon Griswold on some of the alternatives – Dependency Injection Options for Java.

A Spring Framework Example

Consider a standard MVC patterned application that has Models, Services and DAO’s.  Using Spring, you would have to set up an application context, fire up a Spring instance. Using either configuration files or Spring Web MVC Annotations, your code may look something like this:

Login Controller:

@Controller
public class LoginController {

	@Autowired
	private LoginService loginService;

	@RequestMapping (method = RequestMethod.POST, value = "/login.do")
	public String performLogin(@ModelAttribute ("user") User user, Errors errors, ModelMap model, HttpServletRequest request, HttpServletResponse response) {
		String username = user.getUsername();
		String password = user.getPassword();

		// business logic here
		loginService.login(username, password, errors);

		return “some_View_Name_Here”;
	}
}

At the controller level, Spring allows us to annotate the class (@Controller), annotate a single method to a specific URL (@RequestMapping) and inject any required objects we need (@Autowired).

Login Service:

@Service
public class LoginService extends BaseService<User> {

	@Autowired
	private UserDao userDao;

	/**
	 * Login the user with the given username/passsword.
	 * @return True if the user was logged in, false otherwise.
	 */
	public void login(String username, String password, Errors errors) {
		if (username != null && username.trim().length() > 0 && password != null && password.trim().length() > 0) {
			User user = userDao.findByUsername(username);
			if (user == null) {
				errors.reject("username.invalid");
			} else {
				String persistedPassword = user.getPassword();
				if (passwordsMatch(password, persistedPassword)) {
					// business logic here
				}
			}
		} else {
			// error handling logic here
		}
	}
}

At the service level, Spring allows us to annotate the class as a Service (@Service) and inject components we need (@Autowired).

User Dao:

@Component
public class UserDao extends BaseDao<User> {
	public User findByUsername(String username) {
		User result = null;
		Query query = getSession().getNamedQuery(User.FIND_BY_USERNAME);
		query.setString("username", username);
		List<User> users = query.list();
		if (users != null && users.size() > 0) {
			result = users.get(0);
		}
		return result;
	}
}

Finally, at the DAO level, I annotated the class (@Component – so that it may be found by Spring and be injected in other places as need be).

What was snipped from this code example is all the other wiring to setup database access and connection pools.  The scope of this article focuses on the use of Google Guice to wire together your application and not necessarily the business end of database access, etc.

The use of Spring and Annotations makes this code clean and concise. It isn’t littered with extra configuration and setup necessary to get all the pieces the code needs to do it’s job.

For Android developers, here is where RoboGuice comes in.

RoboGuice Setup

The first step in setting up an Android application with RoboGuice is obviously to download it and include it in your project.  For brevity, I’ll skip those steps and assume you have that accomplished.

The next step is to make your application a RoboApplication.  To do this, simply have your main Android Application class extend the RoboApplication object:

public class MyAndroidApplication extends RoboApplication {

	@Override
	protected void addApplicationModules(List<Module> modules) {
		modules.add(new MyModule());
	}
}

You will also need to create a Module object as follows:

public class MyModule implements Module {
	@Override
	public void configure(Binder arg0) {
	}
}

Configuring modules for Guice/RoboGuice is more of an advanced topic that we’ll cover in a later article.  For now, this will suffice.

The next step is to have each of your Activity classes extend RoboActivity.

public class AndroidWithGuiceActivity extends RoboActivity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}
}

Now you are ready to begin coding your application and injecting objects into your Activities.  Here is a basic User Login example. First lets create a User object

public class User {

	private String username;
	private String password;

	public String getPassword() {
		return password;
	}

	public String getUsername() {
		return username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setUsername(String username) {
		this.username = username;
	}
}

Next, lets setup a Service and DAO for managing and looking up Users:

public class LoginService {

	@Inject
	private UserDao dao;

	public boolean login(String username, String password) {
		boolean result = false;
		User theUser = dao.findByUsername(username);
		if (theUser.getPassword().equals(password)) {
			result = true;
		}

		return result;
	}
}

public class UserDao {

	public User findByUsername(String username) {
		User result = null;
		// perform business logic/lookup of the user here

		return result;
	}
}

Notice the use of the @Inject annotation in the LoginService for injecting the DAO.  When this service gets injected (using the same @Inject annotation) into the Activity RoboGuice handles traversing the object hierarchy and processing all the annotations.  Here is what our Activity looks like now:

public class AndroidWithGuiceActivity extends RoboActivity {

	@Inject
	private LoginService loginService;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		String username = "someUsername"
		String password = "somePassword";

		boolean loggedIn = loginService.login(username, password);
		if (loggedIn) {
			// congrats!
		} else {
			// what did you do?!
		}
	}
}

As mentioned, our Activity extends RoboActivity and now can use the @Inject annotation to inject any component we need. RoboGuice handles all the work to ensure that the LoginService also has been injected with everything it needs.

RoboGuice is a straightforward, lightweight Dependency Injection framework that gives us Spring-like functionality in an Android environment.  There is much more that it can do for you, but hopefully this overview gets you started down the right path.

Our next article will explore some more advanced uses and features of RoboGuice such as injecting Android views, resources and much more.  If you would like to download the sample code from this article, a zip file containing an Eclipse project can be found herePlease see Part Two of this Dependency Injection series here.

— Adi Rosenblum, [email protected]

 

0 0 votes
Article Rating
Subscribe
Notify of
guest

6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments