Apple 的 iPhone 平台为开发人员提供了一个有趣的机会。借助其小型的交互式触摸屏,iPhone 和 iPod Touch 在很短的时间内迅速吸引了数百万用户。但是这种新颖的设计和专利平台给应用程序开发人员带来了一系列新的挑战。在 2008 年 2 月 Apple 发布其软件开发包 (SDK) 以前,想要在该平台上进行研究的开发人员必须创建模拟 iPhone 的本机界面外观的 Web 应用程序。
幸运的是,使用一系列新的开源工具可以更轻松地完成这项工作。Aptana 的针对 Eclipse 的 iPhone Development 插件可以生成特定于 iPhone 的项目,并在可旋转取景器中预览应用程序。Joe Hewitt 的 iUi、层叠样式表(Cascading Style Sheets,CSS)和 JavaScript 框架包含模拟本机 iPhone 体验的部件和页面集。
在本文中,我们使用 Aptana 和 iUi 创建一个新应用程序:针对 iPhone 的简单 Javadoc 查看器。首先,设计一个在 iPhone 中浏览 Javadoc 的用户界面 (UI),然后创建用于从任何源代码生成 Javadoc 页面的定制 doclet。在此过程中将描述针对 iPhone 的 UI 问题,如何使用这些开源工具简化开发和调试,以及 iPhone 开发的未来趋势。
工具快速入门
首先安装 Aptana 并下载 iUi:
http://update.aptana.com/3.2
对其进行定义。
一切就绪之后,请使用 Eclipse 创建一个名为 iDoc 的新 iPhone Project,如图 1 所示。
图 2 显示了生成的项目,其中包含简单 iPhone 应用程序。
注意由 Aptana 的基本编辑器提供的突出显示的语法,它支持 HTML、CSS 和 JavaScript。
iPhone Preview 模式和应用服务器
在文本编辑器的底部,您将看到 Source、iPhone Preview 选项卡,以及系统中安装的所有浏览器(例如,Safari Preview、Firefox Preview)。单击 iPhone Preview 查看示例应用程序在 iPhone 中的外观。在浏览器外部单击可以旋转电话,单击电话标题栏可以隐藏导航栏。下面显示了水平显示的 iPhone Preview 模式。
使用 iPhone Preview 模式可以节省大量时间:可以快速测试新设计想法并重复进行开发而无需离开计算机。当应该在实际的 iPhone 上测试您的应用程序时,Aptana 的内置应用服务器将十分有用。单击 Eclipse 工具栏中的 Run 图标启动服务器。图 4 显示了在 Eclipse 中运行的应用服务器。
如果通过 WiFi 连接将 iPhone 连接到本地网络,则可以访问服务器窗口中显示的 URL。单击 E-mail this url 并向 iPhone 中的电子邮件帐户发送一条消息,这可以省去一个步骤。单击电子邮件中的链接,应用程序将在 iPhone 的 Web 浏览器中启动。
iUi 演示:剧院清单 Web 应用程序
虽然 Aptana 的启动应用程序包含特定于 iPhone 的 HTML 和 CSS 文件,但是这些文件的功能有限。一种更好的备用解决方案是使用 iUi 框架,此框架拥有一组丰富的自定义部件和 JavaScript 效果,可以精确地模拟本机 iPhone 界面。
解压缩已下载的 iUi 发行版 iui-0.13.tar,然后把文件复制到 Eclipse 的 iDoc Project 中。图 5 显示了包含 iUi 的项目。
iUi 的演示 Web 应用程序可以在上面展开的 samples 文件夹中找到。其中包括音乐浏览器、剧院清单和类似 Digg 的站点。使用 Aptana 的 iPhone Preview 模式,我们可以在 Eclipse 中查看这些组件。图 6 显示了剧院清单 Web 应用程序 (samples/theaters/index.html) 的搜索页面。
注意,该演示与本机 iPhone 的界面外观极为相似。使用这些预打包的部件可以快速开发 iPhone Web 应用程序。
设计 UI
在本例中,将为 iPhone 创建一个名为 iDoc 的 Javadoc 查看器。由 Sun Microsystems 的标准 Javadoc 生成器创建的紧密 HTML 文件在台式机上一切正常,但是在 iPhone 中却很难导航和读取。iDoc 将生成 iPhone 支持的 Javadoc —— 非常适合于在地铁中浏览应用程序编程接口 (API) 或者让合作的编程团队中的观察员帮助解决困难。
iPhone 人机接口指南
在开始设计 iDoc 的 UI 之前,一定要先了解 iPhone 开发与普通 Web 开发的不同之处。图 7 来自 Apple 的 iPhone Dev Center(请参阅 参考资料),很好地总结了两者的不同之处:手指不是鼠标。这样做得不到桌面应用程序中的像素精度,但是通过轻敲、轻弹和轻压将开启一个丰富的新用户交互模型。此外,iPhone 与用户一起移动并且通常用于有干扰的环境中,因此应用程序需要能够快速容易地访问目标信息。
图 7. 手指不是鼠标
Apple 的 iPhone 人机接口指南(请参阅 参考资料)定义了三种类型的 iPhone Web 内容。
标准 Javadoc 页面属于第一种类型,与 iPhone 中的 Safari 兼容。这些页面可以正确显示,但是要求很好地处理轻压和轻弹才能找到相关信息。iDoc 针对的是完整的 iPhone 应用程序。虽然不能与其他服务集成,但是 iDoc 的接口能够在 iPhone 中很好地使用。
iDoc UI
针对 iPhone 进行开发时,必须只关注 iPhone。应用程序应当快速地完成特定任务,不应该尝试包括所有可能的功能。使用 iDoc,用户必须找到关于 Java 类的基本文档,例如类名、方法名、方法签名和注释。通过指向目标详细信息页面的三个导航级别显示这些信息。
为了使 iDoc 保持整齐并且以任务为目的,需要省略一些传统 Javadoc 功能。例如,不显示包描述注释。由于这些功能通常不包含有用信息(例如,acme.client 包含客户机代码),并且有时被同时省略,因此把它们从 iDoc 中移除并简化接口就显得十分有意义。
要获得三个导航级别,请使用边对边 (edge-to-edge) 列表。这是在本机 iPhone 应用程序中常用的构造,用于浏览联系人、电子邮件和音乐。边对边列表将在 44 像素的等高行中显示项,并且有助于在大量信息中滚动查找。Apple 的 iPhone 人机接口指南 提供了构造边对边列表的规格,包括字体、字体大小和边框间距。iUi 框架用 CSS 和 JavaScript 语言实现这些规格,允许您创建像本机 iPhone 组件那样显示的简单 HTML 列表。
清单 1 显示了页眉,以及 java.applet 和 java.rmi 包的前两个导航级别。
清单 1. 带有页眉和前两个导航级别的 HTML 文档
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>iDoc</title> <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/> <style type="text/css" media="screen">@import "iui/iui.css";</style> <style type="text/css" media="screen">@import "iDoc.css";</style> <script type="application/x-javascript" src="iui/iui.js"></script> </head> <body > <div class="toolbar"> <h1 id="pageTitle"></h1> <a id="backButton" class="button" href="#"></a> </div> <ul id="home" title="Packages" selected="true"> <li><a href="#java.applet">java.applet</a></li> <!-- more packages...--> <li><a href="#java.rmi">java.rmi</a></li> </ul> <ul id="java.applet" title="java.applet"> <li class="group">Interfaces</li> <li><a href="java.applet.AppletContext.html"> AppletContext</a></li> <li><a href="java.applet.AppletStub.html"> AppletStub</a></li> <li><a href="java.applet.AudioClip.html"> AudioClip</a></li> <li class="group">Classes</li> <li><a href="java.applet.Applet.html">Applet </a></li> <li><a href="java.applet.Applet.AccessibleApplet.html"> AccessibleApplet</a></li> </ul> <ul id="java.rmi" title="java.rmi"> <li class="group">Interfaces</li> <li><a href="java.rmi.Remote.html"> Remote</a></li> <li class="group">Classes</li> <li><a href="java.rmi.MarshalledObject.html"> MarshalledObject</a></li> <li><a href="java.rmi.Naming.html"> Naming</a></li> <li><a href="java.rmi.RMISecurityManager.html"> RMISecurityManager</a></li> <li class="group">Exceptions</li> <li><a href="java.rmi.AccessException.html"> AccessException</a></li> <li><a href="java.rmi.AlreadyBoundException.html"> AlreadyBoundException</a></li> <li><a href="java.rmi.ConnectException.html"> ConnectException</a></li> <li><a href="java.rmi.ConnectIOException.html"> ConnectIOException</a></li> <li><a href="java.rmi.MarshalException.html"> MarshalException</a></li> <li><a href="java.rmi.NoSuchObjectException.html"> NoSuchObjectException</a></li> <li><a href="java.rmi.NotBoundException.html"> NotBoundException</a></li> <li><a href="java.rmi.RemoteException.html"> RemoteException</a></li> <li><a href="java.rmi.RMISecurityException.html"> RMISecurityException</a></li> <li><a href="java.rmi.ServerError.html"> ServerError</a></li> <li><a href="java.rmi.ServerException.html"> ServerException</a></li> <li><a href="java.rmi.ServerRuntimeException.html"> ServerRuntimeException</a></li> <li><a href="java.rmi.StubNotFoundException.html"> StubNotFoundException</a></li> <li><a href="java.rmi.UnexpectedException.html"> UnexpectedException</a></li> <li><a href="java.rmi.UnknownHostException.html"> UnknownHostException</a></li> <li><a href="java.rmi.UnmarshalException.html"> UnmarshalException</a></li> </ul> |
图 8 显示了使用边对边列表生成的顶层选择包导航级别。
图 8. 像导航本机 iPhone 应用程序一样导航 Javadoc 包
图 9 显示了在 iPhone Preview 模式下显示的最终的 java.rmi 包。
图 9. 在 java.rmi 包中导航接口、类和异常
对于 iDoc 的目标详细信息页面,使用另一种 iPhone 构造:圆角矩形列表。这些列表对于分组信息十分有用,并且 iPhone 中的设置面板都使用这种列表。使用圆角矩形列表可以分隔方法签名与参数及异常清单。在 V0.13 中,iUi 只支持将圆角矩形列表用于表单输入;将其元素用于静态文本将生成格式错误的块。 使用定制的 iDoc.css 文件扩展这些 CSS(如清单 2 所示),以添加用于显示带有静态文本的圆角矩形列表的 textRow
元素。
清单 2. 定制 textRow
CSS 扩展以正确显示静态文本
/* Adding a new row CSS style to iUi for displaying blocks of text */ .textRow { position: relative; border-bottom: 1px solid #999999; -webkit-border-radius: 0; text-align: right; } .textRow > p { text-align: left; margin: 5px 8px 5px 10px; padding: 0px 0px 0px 0px; } fieldset > .textRow:last-child { border-bottom: none !important; } |
清单 3 显示了 java.math.BigDecimal
的一种构造方法的详细信息页面。
清单 3. 使用 textRow
元素的 HTML 详细信息页面
<div id="java.math.BigDecimal(long,java.math.MathContext)" title="BigDecimal" class="panel"> <fieldset> <div class="textRow"><p><b> public BigDecimal(long, MathContext)</b></p></div> <div class="textRow"><p>Translates a <code>long</code> into a <code>BigDecimal</code>, with rounding according to the context settings. The scale of the <code>BigDecimal</code>, before any rounding, is zero. </p></div> </fieldset> <h2>Parameters</h2> <fieldset> <div class="textRow"><p><b>long val </b>: <code>long</code> value to be converted to <code>BigDecimal</code>.</p></div> <div class="textRow"><p><b>MathContext mc </b>: the context to use.</p></div> </fieldset> <h2>Throws</h2> <fieldset> <div class="textRow"><p><b>ArithmeticException </b>: if the result is inexact but the rounding mode is <code>UNNECESSARY</code>.</p></div> </fieldset> </div> |
<fieldset>
标记内的所有内容都位于圆角矩形内,textRow <div>
用于分隔行。带有 <h2>
标记的标题显示为列表上方的组标签。图 10 显示了最终页面。
图 10. java.math.BigDecimal 中的构造函数的详细视图
拥有三个导航级别和目标详细信息页面后,UI 就完成了。iDoc 使用户可以专注于具体任务。借助 iUi 框架和一些定制的 CSS,它看上去很像本机 iPhone 应用程序。
开发 iDoc
现在已经设计了 UI,接下来需要编写代码来生成 HTML 文件。创建一个插入到 Sun 的 javadoc
命令中的简单 doclet。我们的示例将使用标准 java.* 包,但是 iDoc 可以从任何源代码生成 Javadoc。使用 OpenJDK 源代码,因为它可以公开获得并且 GNU Public License (GPL) V2 许可证允许我们生成和发布其 Javadoc。
使用 iDoc,只需迭代包和类并调用方法打印上述格式的静态 HTML 页面。清单 4 显示打印目标详细信息页面的方法。
清单 4. 输出详细信息页面的 Doclet 代码
private void printDetail(PrintStream p, ProgramElementDoc doc, String id, String name) { divHeader(p, id, name, "panel"); textHeader(p, null); textRow(p, getSignature(doc)); textRow(p, getCommentText(doc.commentText())); textFooter(p); if (doc instanceof ExecutableMemberDoc) { printMethodDetail(p, (ExecutableMemberDoc) doc); } divFooter(p); } private void printMethodDetail(PrintStream p, ExecutableMemberDoc field) { if (field.parameters().length > 0) { textHeader(p, "Parameters"); for (int i=0; i<field.paramTags().length; i++) { textRow(p, "<b>" + field.parameters()[i].typeName() + " " + field.paramTags()[i].parameterName() + "</b>: " + getCommentText(field.paramTags()[i].parameterComment())); } textFooter(p); } if (field.throwsTags().length > 0) { textHeader(p, "Throws"); for (int i=0; i<field.throwsTags().length; i++) { textRow(p, "<b>" + field.throwsTags()[i].exceptionName() + "</b>: " + getCommentText(field.throwsTags()[i].exceptionComment())); } textFooter(p); } } |
代码是通用的,这样 printDetail()
将处理类描述、字段、构造函数和方法的输出。后两种类型是 ExecutableMemberDoc
的子类,因此打印关于其参数和已抛出异常的附加信息。
Aptana 的 iPhone Preview 模式将帮助调试输出文件。在每次迭代后,您可以快速单击该应用程序查找已设计界面中的不一致性。但是,使用 Preview 模式可以掩盖性能问题:现代计算机的运行速度比 iPhone 的 620-MHz ARM 处理器快三至五倍。此外,用户经常通过速度慢的蜂窝网络下载页面,因此必须用实际 iPhone 运行您的应用程序。
性能问题
当我在 iPhone 中测试查看 iDoc 时,我发现输出一个大型 HTML 文件将导致跳帧和性能下降。要解决此问题,创建一个用于导航包名/类名的主文件,然后为带有注释和方法细节的每个类创建独立文件(参见清单 5)。虽然此过程将生成大量文件,但是各个文件大小都非常小,并且应用程序运行得十分流畅。
清单 5. Doclet 代码将迭代每个包,然后为每个类创建文件
out = new FileOutputStream(index); p = new PrintStream(out); printHeader(p); PackageDoc[] packages = root.specifiedPackages(); Arrays.sort(packages); printPackages(p, packages); for (int i=0; i<packages.length; i++) { printPackageDetail(p, packages[i]); } for (int i=0; i<packages.length; i++) { ClassDoc[] classes = packages[i].allClasses(); Arrays.sort(classes); for (int j=0; j<classes.length; j++) { // Creating a separate file for each class. PrintStream p2 = new PrintStream(new FileOutputStream(getFilename(classes[j]))); printClassDetail(p2, classes[j]); p2.close(); } } printFooter(p); p.close(); |
运行 iDoc
在经过该性能增强之后,就能运行 iDoc 了。为 OpenJDK 中的 51 个 java.* 和 javax.* 包(表示 1,304 个类)生成 Javadoc,然后把所有内容上传到 Web 服务器中。这包括超过 16 MB 的文件,但是主要导航页面只有 112 KB,并且每个单独类的详细信息页面平均为 13 KB。即使在使用 EDGE 网络时,应用程序也能够快速响应。如果您已经拥有了 iPhone,请访问 iDoc 站点(请参阅 参考资料)并尝试使用,也可以下载 iDoc 来为您自己的代码库生成特定于 iPhone 的 Javadoc。图 11 显示了最终的应用程序。
图 11. 用于 iPhone 的全部 51 个包的 Javadoc
可能对 iDoc 进行的扩展包括支持显示 Java 5 泛型,以及更智能地捕捉 Javadoc 注释内的标记来实现页面之间的链接。如果您有兴趣添加 iDoc 的功能,则可以下载完整的源代码.
iPhone 开发的前景
2007 年 10 月,Steve Jobs 宣称 Apple 将于 2008 年 2 月发布 iPhone SDK。详细信息很少,因为这是在 2007 年 12 月编写的,但是 SDK 将允许您在不需要使用 Safari 的情况下创建能够在 iPhone 上本机运行的应用程序。给定 iPhone 底层架构之后,开发平台很可能是类似于 Mac OS X 的 Cocoa 和 Objective-C。Apple 主管人员的最新评论暗示第三方应用程序将需要接受某种类型的认证过程。
通过在本机运行,需要高级动画、图形和网络访问的应用程序将从中获益。不过,即使在发布了 SDK 之后,iPhone 的 Web 开发仍会是一个吸引人的主题。Web 应用程序很容易创建和部署。诸如 Aptana 和 iUi 之类的工具简化了开发,并且能够快速创建 Web 应用程序。正如 iDoc 所展示的,没有必要等待 SDK 的发布:使用现有的工具,您可以创建具有本机界面外观的全功能 iPhone Web 应用程序。