假设您有一天早上醒来,心想:“嘿,我今天要做一个 Android 应用。” 首先,这是一个不错的选择!截至 6 月底,每天有 500,000 台 Android 设备被激活,甚至超过了 iPhone。这意味着您的应用拥有庞大的潜在受众。此外,Android 是用 Java 构建的。这可能看起来不是什么大事,但我曾经在 Objective-C 和 iOS 平台上工作过几年,虽然我现在对此非常熟悉,但相比 Android,iOS SDK 的学习曲线更为陡峭。当我刚开始使用 Android SDK 时,Android 感觉更容易上手。尽管如此,与您过去构建的任何其他 Java 应用程序相比,它仍然存在一些明显的差异,我将在第一个部分介绍其中一些。
再往前推移,您完成了第一个应用,并将其提交到了 Android Market。恭喜您,您的朋友们都在下载您的应用并在 Twitter 上讨论。现在该开始制作您的第二个应用了。您花了几天时间,突然意识到您开始重用第一个应用的代码,这本身并不是坏事。代码重用很有价值。但您会注意到有很多样板代码经常重复出现,这会分散您对业务逻辑的注意力。幸运的是,有一些方法可以改进这一点。
在这篇博文中,我将概述 Android 和应用程序生命周期,并讨论该框架施加的一些限制。我还将回顾一些可以帮助您清理 Android 代码、专注于应用目标的技术和第三方项目。
Android 概览
让我们从简要概述 Android 的工作原理开始。Android 应用程序(应用)使用 Java 构建,并编译为类文件。然后,类文件被编译为 Dalvik 可执行(DEX)格式,以便在 Android 使用的 Dalvik 虚拟机上运行。转换为 DEX 格式后,类文件会被打包成 Android 包(APK)分发到设备上。由于使用了 DEX 格式,Dalvik VM 并不是真正的 Java 虚拟机,因为它不操作 Java 字节码。此外,Dalvik VM 基于 Apache Harmony 项目的一个子集作为其核心类库。这意味着许多您在 Java SE 中习惯使用的类和方法是可用的,但肯定不是全部。我发现 Android 开发者网站上的 API 参考和Android 开发者网站对于回顾这些差异是非常宝贵的资源。
默认情况下,每个 Android 应用程序都会由 Android 操作系统分配一个唯一的 Linux 用户 ID。当系统启动应用程序时,应用程序会在自己的 Linux 进程中,在其自己的虚拟机 (VM) 中运行。系统会根据需要管理该进程的启动和关闭。正如您所料,这意味着每个应用程序与其他正在运行的应用程序隔离运行。安装时,应用程序可以请求访问硬件功能或与其他应用程序交互的权限。用户选择授予应用程序这些权限或不安装它。应用程序所需或请求的权限在每个应用程序的 Android Manifest 文件中定义。这是一个 XML 文件,列出了应用程序的所有组件以及这些组件的任何设置。应用程序组件的四种类型是活动 (activities)、服务 (services)、内容提供者 (content providers)和广播接收器 (broadcast receivers)。在本帖中,我将重点介绍活动。
活动基本上代表 Android 应用程序的一个屏幕。例如,Twitter 应用可能有一个登录屏幕、一个显示推文列表的屏幕和一个撰写新推文的屏幕。这些屏幕中的每一个都代表了应用程序中的不同活动。作为开发人员,您永远不会自己实例化一个活动对象。活动是通过发送一个名为Intent 的异步消息来激活的,如下面的示例所示。
startActivity(new Intent(context, HomeActivity.class));
当调用startActivity(Intent intent) 时,系统会创建一个新实例或重用现有实例以向用户显示活动。关键点在于,系统控制着应用程序和每个活动的启动、停止、创建和销毁。如果您想与此过程交互,那么应用程序和活动类会提供不同生命周期事件的方法,您可以在子类中覆盖它们。
依赖注入
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 相当容易。如前所述,系统会创建应用程序实例。因此,通过扩展应用程序,您可以有效地创建一个单例依赖项实例,然后该应用程序中的任何活动都可以访问它。
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() 的方法,它返回一个对拥有该活动的应用程序对象的引用。我们只需将其强制转换为 MainApplication,就可以访问 MyService 的 getter 方法。当然,Activity 现在必须“知道”应用程序,这可能看起来是一个缺点。但请记住,Activity 已经知道它的应用程序。该方法是内置的。
public class MainActivity extends Activity {
private MyService service;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainApplication app = (MainApplication…