Android 应用程序中的整洁代码

工程 | Roy Clarkson | 2011 年 8 月 26 日 | ...

假设有一天早上你醒来,心想:“嘿,我今天要构建一个 Android 应用。”首先,这是一个不错的选择!截至 6 月底,每天有 500,000 台 Android 设备被激活,甚至超过了 iPhone。这意味着您的应用拥有庞大的潜在用户群体。此外,Android 是使用 Java 构建的。这可能看起来并不重要,但我已经在Objective-C 上工作了几年iOS 平台,虽然我现在对此感到非常满意,但iOS SDK 提供的学习曲线比我在 Android 上遇到的要陡峭。当我第一次开始使用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 类和方法都可用,但肯定不是全部。我发现API 参考Android 开发者网站上是一个宝贵的资源,可以用来回顾这些差异。

默认情况下,每个 Android 应用程序都会由 Android 操作系统分配一个唯一的 Linux 用户 ID。当系统启动应用程序时,它会在其自己的 Linux 进程中,在其自己的虚拟机 (VM) 内运行。系统根据需要管理此进程的启动和关闭。正如您所料,这意味着每个应用程序都与其他正在运行的应用程序隔离运行。安装后,应用程序可以请求访问硬件功能或与其他应用程序交互的权限。用户可以选择授予应用程序这些权限或不安装它。应用程序需要或请求的权限在每个应用程序的 Android 清单文件中定义。这是一个 XML 文件,列出了应用程序的所有组件,以及这些组件的任何设置。四种类型的应用程序组件是活动服务内容提供程序广播接收器。出于本文的目的,我将重点关注活动。

活动基本上代表 Android 应用程序的单个屏幕。例如,一个 Twitter 应用程序可能有一个登录屏幕、一个包含推文列表的屏幕和一个用于撰写新推文的屏幕。这些屏幕中的每一个都代表应用程序中的不同活动。作为开发人员,您永远不会自己实例化活动对象。通过发送称为Intent 的异步消息来激活活动,如下面的示例所示。


startActivity(new Intent(context, HomeActivity.class));

当调用startActivity(Intent intent) 时,系统会创建一个新实例或重用现有实例,以便向用户显示活动。重要的是,系统控制应用程序和每个活动的启动和停止以及创建和销毁。如果您想与此过程交互,那么应用程序和活动类提供了用于不同生命周期事件 的方法,您可以在子类中覆盖这些方法。

依赖注入

Spring Android 项目最近发布了其第四个里程碑 版本。在该版本中,我们继续改进RestTemplateSpring Social 对 Android 的支持,这简化了进行 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;
    }
}

活动类有一个名为getApplication() 的方法,该方法返回对拥有该活动的应用程序对象的引用。我们只需将其强制转换为 MainApplication,就可以访问 MyService 的 getter 方法。当然,活动现在必须“了解”应用程序,这似乎是一个缺点。但请记住,活动已经了解其应用程序。该方法是内置的。


public class MainActivity extends Activity  {

    private MyService service;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MainApplication app = (MainApplication…

本周 Spring:2011 年 8 月 23 日

工程 | Josh Long | 2011 年 8 月 24 日 | ...

欢迎来到另一期“本周 Spring”,随着我们接近下周的VMworld 2011,事情发展得很快。我想邀请所有与会者参观 VMWorld Spring 展位上的专家技术人员。如果您阅读了这份每周综述,请告诉我。本周有很多内容要讨论,所以让我们开始吧!

    <li>The preliminary session schedule has been published for <a href="http://www.springone2gx.com">SpringOne 2GX 2011</a>. This year's show is going to be another fantastic mix of deep technical content, cutting edge development and the absolute best place to learn about everything in the Spring universe. Be sure to <a href="http://springone2gx.com/conference/chicago/2011/10/register">register now</a>!</li>
    
    <LI> <a href="http://static.springsource.org/spring/docs/3.0.6.RELEASE/changelog.txt">Spring 3.0.6's was just released!</a>   		 
    	 This release addresses over 50 minor issues and includes…

面向 Spring 开发人员的 Micro Cloud Foundry

工程 | Josh Long | 2011 年 8 月 24 日 | ...

今天,VMware 团队发布了Micro Cloud Foundry,这是一个完整的、本地版本的流行的开源平台即服务,允许开发人员在他们的 Mac 或 PC 上运行一个功能齐全的云。使用 Micro Cloud Foundry,开发人员可以在本地构建端到端的云应用程序,而无需费力配置中间件,同时保留部署位置的选择,并能够扩展他们的应用程序而无需更改一行代码。

Micro Cloud Foundry 当然支持 Spring 和 Java,但也为 Scala、Node.js 和 Ruby 提供了运行时环境,以便您可以释放您内心的多语言程序员!Micro Cloud Foundry 还提供了许多服务,如 MongoDB、MySQL 和 Redis,可以立即使用,无需进行大量安装和配置。借助内置的动态 DNS 支持,开发人员可以在他们工作的任何地方运行他们的 Micro Cloud Foundry——无论是在家、办公室还是咖啡店——而无需任何重新配置。在 Micro Cloud Foundry 上创建和测试应用程序后,您可以轻松地部署您的…

从 Grails 使用 Micro Cloud Foundry

工程 | Peter Ledbrook | 2011 年 8 月 24 日 | ...

早在 4 月,VMware 就向世界推出了 Cloud Foundry,随之而来的是为 Grails 开发人员提供的超简单的应用程序部署。几个月后,拼图的另一块也到位了:Micro Cloud Foundry。您现在可以拥有自己的 Cloud Foundry 实例用于测试或任何其他用例。当然,从 Grails 使用它非常容易。

那么什么是 Micro Cloud Foundry 呢?以下屏幕截图简要概述了该产品,然后引导您完成下载、安装和配置过程。最后,您将看到如何…

Grails 2.0 倒计时:数据库迁移

工程 | Peter Ledbrook | 2011 年 8 月 17 日 | ...

Grails 的众多优点之一是它可以根据您的域模型自动创建数据库模式。诚然,这是 Grails 使用的 Hibernate 的一个特性,但它仍然可以帮助您快速开始使用数据库驱动的 Web 应用程序,而无需担心数据库模式。

您的应用程序迁移到生产环境后会发生什么?在开发过程中,服务器运行之间丢失数据不是什么大问题。但是您不能在生产环境中简单地删除数据库。因此,这排除了dbCreate数据源的“create”和“create-drop”值…

云端聊天:第 1 部分

工程 | Mark Fisher | 2011 年 8 月 16 日 | ...

上周,RabbitMQ 作为Cloud Foundry上的服务可用性被宣布。现在,在 Cloud Foundry 上运行的任何应用程序都可以通过 RabbitMQ 代理发送和接收消息,该代理可以通过单个命令(例如 'vmc create-service rabbitmq')作为服务进行配置。消息服务的实例可以在应用程序之间共享,并且由于 RabbitMQ 是一个基于协议的代理,因此这些应用程序甚至可以用不同的语言编写。因此,对于那些有兴趣在云中运行模块化、多语言、事件驱动的应用程序的人来说,这是一个令人兴奋的公告。我将…

配置 Spring 和 JTA 而无需完整的 Java EE

工程 | Josh Long | 2011 年 8 月 15 日 | ...

Spring 通过其PlatformTransactionManager接口和实现层次结构提供了丰富的交易管理支持。Spring 的事务支持为众多 API 的事务语义提供了统一的接口。从广义上讲,事务可以分为两类:本地事务和全局事务。本地事务是指仅影响一个事务资源的事务。大多数情况下,这些资源有自己的事务 API,即使事务的概念没有明确地公开。通常,它以会话的概念公开,…

超越 FactoryBean

工程 | Josh Long | 2011 年 8 月 10 日 | ...

我在我之前的帖子中查看了基本的FactoryBean是什么。虽然FactoryBeans很重要——了解它们的作用可以帮助您更有效地浏览框架——但从 Spring 3.0 和即将推出的 Spring 3.1 开始,它们在很大程度上不再是推荐的任务方法。

FactoryBean的全部意义在于隐藏对象的构造——要么是因为它非常复杂,要么是因为它不能简单地使用 Spring 容器使用的典型以构造函数为中心的方 法进行实例化(也许需要查找?也许需要一个静态注册方法?)Spring 还支持 XML 格式中的factory-method属性。Java 配置方法提供了一个在概念上类似(实际上,结果相同)的替代方案,但具有更简洁、类型安全的替代方案。

Spring 3.0 引入了 Java 配置,允许您使用 Java 定义 bean。例如,要使用 XML 将常规的javax.sql.DataSource注册到 Spring,您很可能会将敏感配置信息(如数据库密码)委托给属性文件,并使用 Spring 实例化javax.sql.DataSource,如下所示


<beans ...>
	<context:property-placeholder location = "ds.properties" />

	<bean id = "ds" class = "a.b.c.MySqlDataSource">
	  <property name = "user" value = "${ds.user}"/>
	  <property name = "password" value = "${ds.password}"/>
	</bean>
</beans>

这是一个简单的 bean,可以自然地转换为 Java 配置。它看起来像这样

 
import a.b.c.* ;
	
@Configuration 
@PropertySource("ds.properties") 
public class MyConfiguration { 
    @Inject private Environment env ; 
	
    @Bean public MySqlDataSource ds(){ 
        MySqlDataSource ds = new MySqlDataSource () ; 
        ds.setUser( env.getProperty("ds.user") );
        ds.setPassword( env.getProperty("ds.password…

什么是 FactoryBean?

工程 | Josh Long | 2011 年 8 月 9 日 | ...

在这篇文章中,我将介绍 Spring 的org.springframework.beans.factory.FactoryBean<T>接口。此接口的定义是


public interface FactoryBean<T> {
  T getObject() throws Exception;
  Class<T> getObjectType();
  boolean isSingleton();
}

FactoryBean是一种模式,用于将有趣的对象构造逻辑封装在类中。例如,它可以用于以可重用的方式编码复杂对象图的构造。通常,这用于构造具有许多依赖项的复杂对象。当构造逻辑本身高度易变并依赖于配置时,也可能使用它。FactoryBean也有助于 Spring 构造它本身无法轻松构造的对象。例如,为了注入对从 JNDI 获取的 bean 的引用,必须首先获取该引用。您可以使用JndiFactoryBean以一致的方式获取此引用。您可以将FactoryBeangetObject()方法的结果注入任何其他属性。

假设您有一个Person类,其定义如下


public class Person { 
 private Car car ;
 private void setCar(Car car){ this.car = car;  }	
}

以及一个FactoryBean,其定义如下


public class MyCarFactoryBean implements FactoryBean<Car>{
  private String make; 
  private int year ;

  public void setMake(String m){ this.make =m ; }

  public void setYear(int y){ this.year = y; }

  public Car getObject(){ 
    // wouldn't be a very useful FactoryBean 
    // if we could simply instantiate the object…

本周 Spring:2011 年 8 月 2 日

工程 | Josh Long | 2011 年 8 月 3 日 | ...

欢迎来到“本周 Spring”的另一期。8 月已经开始,很快,在 8 月底,VMworld 2011 即将到来。此后不久,SpringOne 将在这里举行。它将很快变得非常火爆,所以做好准备!本周的“本周 Spring”包含了来自 Chariot Solutions 的 Gordon Dickens 的大量有趣内容。感谢 Gordon 提供所有精彩的阅读内容!

  1. Spring 的创始人兼思想领袖 Rod Johnson 在今年早些时候在 TheServerSide 做了主题演讲。这篇文章转述了该主题演讲的一些内容,包括他对云计算、SOA 等的看法。查看一下。
  2. <LI> 
    	The video of the recent webinar, "<A href="http://www.springsource.org/node/3194">What's New in Apache Tomcat 7</a>," is now available on the <a href="http://www.youtube.com/SpringSourceDev">SpringSourceDev YouTube channel</a>.   
    </LI> 
    <LI>Luke Taylor has some great content on how to <a href="http://blog.springsource.com/2011/08/01/spring-security-configuration-with-scala/">configure Spring Security with the Scala DSL</a> he's been developing. Check it out! 
    </LI> 
    <LI> 
    	<a href= "http://www.springsource.org/node/3192">Spring Data JDBC Extensions with Oracle Database Support</a>…

获取 Spring 新闻通讯

与 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部