假设有一天早上你醒来,心想:“嘿,我今天要做一个 Android 应用。”首先,好主意!截至六月底,每天有 50 万台 Android 设备被激活,甚至超过了 iPhone。这意味着你的应用拥有庞大的潜在用户群。此外,Android 是用 Java 构建的。这可能看起来没什么大不了,但我已经在 iOS 平台上用 Objective-C 开发了几年,虽然我现在用得很顺手,但 iOS SDK 的学习曲线比我在 Android 上遇到的要陡峭。刚开始使用 Android SDK 时,Android 给我的感觉更易于入门。话虽如此,Android 与你过去构建过的任何其他 Java 应用还是有一些明显的区别,我将在第一部分讨论其中的一些。
随着时间的推移,你完成了第一个应用,并将其提交到了 Android Market。恭喜你,你的朋友们都在下载你的应用并转发推文。现在是时候开始你的第二个应用了。你花了几天时间,突然意识到你开始重复使用第一个应用中的代码,这本身并不是一件坏事。代码重用是有价值的。但是你注意到有很多样板代码往往会重复出现,这会分散你专注于业务逻辑的注意力。幸运的是,有一些方法可以对此进行改进。
在这篇博文中,我将概述 Android 及其应用生命周期,并讨论框架带来的一些限制。我还会回顾一些技巧和第三方项目,它们可以帮助你整理 Android 代码,并专注于你想通过应用实现的目标。
Android 概览
让我们先简要介绍一下 Android 的工作原理。Android 应用程序 (app) 使用 Java 构建,并编译成 class 文件。然后,这些 class 文件被编译成 Dalvik Executable (DEX) 格式,以便它们可以在 Android 使用的 Dalvik 虚拟机上运行。转换成 DEX 格式后,class 文件被打包成 Android Package (APK) 用于分发到设备。由于使用了 DEX 格式,Dalvik VM 不是一个真正的 Java 虚拟机,因为它不直接运行 Java 字节码。此外,Dalvik VM 的核心类库是基于 Apache Harmony 项目的一个子集。这意味着你在 Java SE 中习惯使用的许多类和方法是可用的,但肯定不是全部。我发现 Android 开发者网站上的 API 参考是查阅这些差异的宝贵资源。
默认情况下,每个 Android 应用程序都会被 Android 操作系统分配一个唯一的 Linux 用户 ID。当系统启动时,应用程序在其自己的 Linux 进程中运行,并在其自己的虚拟机 (VM) 中运行。系统在需要时管理此进程的启动和关闭。正如你所猜,这意味着每个应用程序与其他正在运行的应用程序是隔离运行的。安装时,应用程序可以请求访问硬件功能或与其他应用程序交互的权限。用户选择授予应用这些权限或不安装它。应用所需或请求的权限在其 Android Manifest 文件中定义。这是一个 XML 文件,列出了应用的所有组件以及这些组件的任何设置。应用程序组件的四种类型是 activities、services、content providers 和 broadcast receivers。出于本文的目的,我将重点介绍 activities。
activities 基本上代表 Android 应用程序的一个屏幕。例如,一个 Twitter 应用可能有一个登录屏幕、一个包含推文列表的屏幕以及一个用于撰写新推文的屏幕。这些屏幕中的每一个都代表应用程序内不同的 activity。作为开发者,你永远不会自己实例化 activity 对象。activities 通过发送一个称为 Intent 的异步消息来激活,如下例所示。
startActivity(new Intent(context, HomeActivity.class));
当调用 startActivity(Intent intent) 时,系统要么创建一个新实例,要么重用一个现有实例,以便向用户显示 activity。重要的一点是,系统控制应用程序和每个 activity 的启动、停止、创建和销毁。如果你想与这个过程进行交互,那么应用程序和 activity 类提供了用于不同生命周期事件的方法,你可以在子类中重写这些方法。
依赖注入
Spring Android 项目最近发布了其第四个里程碑版本。随着这个版本的发布,我们继续改进了对 Android 的 RestTemplate 和 Spring Social 支持,这简化了发出 RESTful HTTP 请求和访问由 OAuth 保护的 REST API 的过程。虽然我们认为这些是对 Android 开发的有价值的补充,但一些开发者提出了关于 Spring Android 中是否可能支持依赖注入的问题,因为你可能知道,Spring Framework 已经提供了一个流行的控制反转 (IOC) 容器,用于在企业级 Java 应用中实现依赖注入。在 Spring Android 的早期规划阶段,依赖注入支持被认为是项目包含的潜在候选。当时,还不清楚这种支持会涉及什么,以及如何实现。因此,我开始研究和调查在 Android 中进行依赖注入的可能方法和限制。
那么,什么是依赖注入?如果你问两个不同的开发者,你可能会得到两个不同的答案。你可能会听到关于 IOC、XML 文件、注解或其他实现细节。实际上,依赖注入只是一种减少耦合的技术,它通过将对象工作所需的内容提供给它,而不是让对象主动获取其环境中的内容。这听起来很简单,你可能会想,这通过类的构造函数和 setter 方法就可以实现,这完全正确。然而,回想一下上面的概览部分,Android 系统驱动着应用的生命周期,所以我们实现这种方式的方法是有限的。
Android 方式
不使用任何第三方库,将依赖项传递给 Activity 是相当容易的。如前所述,系统会创建应用程序实例。因此,通过扩展 application,你可以有效地创建一个单例依赖项实例,然后应用程序中的任何 activity 都可以访问它。
public class MainApplication extends Application {
private MyService service;
@Override
public void onCreate() {
super.onCreate();
service = new MyServiceImpl();
}
public MyService getMyService() {
return this.service;
}
}
activity 类有一个名为 getApplication() 的方法,它返回拥有该 activity 的 application 对象的引用。我们只需将其转换为 MainApplication,就可以访问 MyService 的 getter 方法。当然,现在 activity 必须“知道”这个 application,这看起来可能是一个缺点。但记住,activity 本来就知道它的 application。这个方法是内置的。
public class MainActivity extends Activity {
private MyService service;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainApplication app = (MainApplication…