BlackBerry手机在美国的企业级领域占有非常重要的地位,前不久我们为大家介绍过《BlackBerry应用程序开发方法》,本文我们将为大家介绍如何使用Java语言编写BlackBerry应用程序。
应用程序管理
当BlackBerry设备启动时,VM加载应用程序管理器,它管理在BlackBerry设备上所有运行的程序。对于其他Java程序,应用程序管理器的功能类似操作系统事件的中心调度员一样。
提供用户界面的应用程序扩展了net.rim.device.api.UI.UiApplication类。这个类为应用程序提供方法来注册事件监听者,管理线程以及UI组件。
没有提供用户界面的应用程序扩展了net.rim.device.api.system.Application类。
BlackBerry应用程序开始于main()函数。当一个程序开始时,它的main()线程调用enterEventDispatcher()来开始处理事件。这个线程运行所有绘图以及事件处理的代码,以及登等待应用程序队列里地事件。
当应用程序管理器接收到一个事件时,它将这个事件拷贝到合适的队列里,这个队列可以允许应用程序管理器指挥消息到特定的程序中。例如,前台的应用程序仅接收用户输入的消息。#p#
编写一个例程
扩展UiApplication基类
每个提供用户接口的应用程序扩展了UiApplication基类,UiApplication类为应用程序定义了方法来建立一个事件线程,并且显示和维护Screen对象。
定义 main()
在main()中,为应用程序创建一个新的对象。调用enterEventDispatcher()使应用程序进入事件线程并且开始处理消息。
Java代码
- public static void main(String[] args) { HelloWorld theApp = new HelloWorld(); theApp.enterEventDispatcher();}
定义一个构造子
为你的应用程序定义缺省的构造子。缺省的构造子调用UiApplication.pushScreen()以显示当应用程序启动时出现的屏幕。在本例中,屏幕使一个新的HelloWorldScreen实例,它在下节的代码中定义:
Java代码
- public HelloWorld() { pushScreen(new HelloWorldScreen());}
定义main屏幕
为了定义应用程序UI的主屏幕,扩展MainScreen类。MainScreen类是Screen的子类,它实现了TrackwheelListener和KeyboardListener接口,这些接口接收和响应用户交互。如果你扩展Screen类或者其子类中的一个,你并不是必须实现TrackwheelListener 和KeyboardListener接口。
你的类至少应该重写2个MainScreen的方法:缺省的构造子和onClose().
在这个例子中,构造子调用了MainScreen的构造子。缺省地,MainScreen提供下列特性:
由一个Close菜单项的缺省菜单。
当你点击Close或者按Escape时,缺省的是关闭动作。为了提供客户定制行为,例如显示一个对话框提示,当用户点击Close菜单项或者按Escape按钮,重写onClose().
一个RichTextField 的实例,一个可以接收焦点的只读富文本域 为了得到更多关于增加UI组件到屏幕中的信息,参看40页的“提供屏幕导航”
一个Select菜单项的上下文菜单? 为了得到更多信息,参看60页的“创建定制的上下文菜单”
代码实例
接下来的例子创建了一个屏幕,它包含了一个富文本域。当富文本域接收到焦点时,菜单保安一个Close菜单项和一个Select上下文菜单项。
Java代码
- 例: HelloWorld.java
- /**
- * HelloWorld.java
- * Copyright (C) 2001-2005 Research In Motion Limited. All rights reserved.
- */
- package com.rim.samples.docs.helloworld;
- import net.rim.device.api.ui.*;
- import net.rim.device.api.ui.component.*;
- import net.rim.device.api.ui.container.*;
- import net.rim.device.api.system.*;
- import com.rim.samples.docs.resource.*;
- public class HelloWorld extends UiApplication {
- public static void main(String[] args) {
- HelloWorld theApp = new HelloWorld();
- theApp.enterEventDispatcher();
- }
- public HelloWorld() {
- pushScreen(new HelloWorldScreen());
- }
- }
- final class HelloWorldScreen extends MainScreen {
- public HelloWorldScreen() {
- super();
- LabelField title = new LabelField(“HelloWorld Sample”, LabelField.ELLIPSIS
- | LabelField.USE_ALL_WIDTH);
- setTitle(title);
- add(new RichTextField(“Hello World!”));
- }
- public boolean onClose() {
- Dialog.alert(“Goodbye!”);
- System.exit(0);
- return true;
- }
- }
#p#
重用一般代码
抽象基类可以使你跨越多个类实现和重用一般功能。每个应用程序可以扩展单个基类。在BlackBerry IDE,加入基类到一个库项目中。为每个应用程序创建一个独立的项目,定义库项目的依赖。
代码实例
◆本指南的例程扩展了BaseApp类,它实现下面的功能:
◆扩展UiApplication类
◆实现KeyListener和TrackwheelListener接口
◆定义变量,例如一般的菜单项
定义一个方法创建应用程序菜单。
◆为菜单选择定义一个方法
◆定义一个抽象方法退出程序
Java代码
- 例: BaseApp.java
- /*
- * * BaseApp.java
- * * Copyright (C) 2001-2005 Research In Motion Limited. All rights reserved.
- * */
- package com.rim.samples.docs.baseapp;
- import net.rim.device.api.i18n.*;
- import net.rim.device.api.system.*;
- import net.rim.device.api.ui.container.*;
- import net.rim.device.api.ui.*;
- import net.rim.device.api.ui.component.*;
- import com.rim.samples.docs.resource.*;
- public abstract class BaseApp
- extends UiApplication implements BaseAppResource, KeyListener, TrackwheelListener {
- private MenuItem _closeItem;
- private static ResourceBundle _resources =
- ResourceBundle.getBundle(BUNDLE_ID, BUNDLE_NAME);
- /* Constructor for the abstract base class. */
- public BaseApp() {
- _closeItem = new MenuItem(_resources, MENUITEM_CLOSE, 200000, 10) {
- public void run() {
- onExit();
- System.exit(0);
- }
- };
- }
- /* Override this method to add custom menu items. */
- protected void makeMenu( Menu menu, int instance) {
- Field focus = UiApplication.getUiApplication().
- getActiveScreen().getLeafFieldWithFocus();
- if(focus != null) {
- ContextMenu contextMenu = focus.getContextMenu();
- if( !contextMenu.isEmpty()) {
- menu.add(contextMenu);
- menu.addSeparator();
- }
- }
- menu.add(_closeItem);
- }
- /* Invoked when the trackwheel is clicked. */
- public boolean trackwheelClick( int status, int time ) {
- Menu menu = new Menu();
- makeMenu( menu, 0);
- menu.show();
- return true;
- }
- /* Invoked when the trackwheel is released. */
- public boolean trackwheelUnclick( int status, int time ) {
- return false;
- }
- /* Invoked when the trackwheel is rolled. */
- public boolean trackwheelRoll(int amount, int status, int time) {
- return false;
- }
- public boolean keyChar(char key, int status, int time) {
- /* Intercept the ESC key and exit the application. */
- boolean retval = false;
- switch (key) {
- case Characters.ESCAPE:
- onExit();
- System.exit(0);
- retval = true;
- break;
- }
- return retval;
- }
- /* Implementation of KeyListener.keyDown(). */
- public boolean keyDown(int keycode, int time) {
- return false;
- }
- /* Implementation of KeyListener.keyRepeat(). */
- public boolean keyRepeat(int keycode, int time) {
- return false;
- }
- /* Implementation of KeyListener.keyStatus(). */
- public boolean keyStatus(int keycode, int time) {
- return false;
- }
- /* Implementation of KeyListener.keyUp(). */
- public boolean keyUp(int keycode, int time) {
- return false;
- }
- protected abstract void onExit();
- }
#p#
使用BlackBerry IDE
为了编写,调试和编译应用程序,使用BlackBerry IDE,它是BlackBerry JDE的一部分。
(注:BlackBerry 版本4.1使用了SUN jdk 5.0)
创建一个工作空间
◆在BlackBerry IDE,选择File菜单,点击New Workspace
◆在Workspace name域,输入一个没有文件扩展名的名字。
◆在Create in this directory域,输入一个文档。
◆点击OK.
创建一个项目
(注:在包含工作空间的文件夹下的子目录中创建工程。)
◆在BlackBerry IDE的Project菜单,点击Create New Project.
◆在Project name域,输入一个没有文件扩张名的项目名称。
◆在Create project in this directory域,输入在此文件夹下创建项目的文件夹名称。
◆点击OK。
◆在工作空间文件区域里,双击项目名称来设置项目属性。
为了得到更多关于项目属性的信息,参看BlackBerry Integrated Development Environment Online Help。
创建源文件
(注:保存源文件到和项目文件相同的文件夹下。和所有Java程序一样,为符合你的类使用的包层次关系的源代码创建文件结构。)
◆在BlackBerry IDE的File菜单,点击New。
◆在Source file name域,输入一个带.java文件扩展的文件名。
◆在Create source file in this directory域,输入文件夹名。
◆点击OK。
◆在编辑器区域,右击文件,然后点击Insert into project.
◆选择一个项目。
◆点击OK。
和BlackBerry IDE集成源文件管理工具
你可以通过不同的源文件控制程序来使用BlackBerry IDE。BlackBerry IDE允许你为源文件控制程序设置“check out”, “add new file”和“revert”选项。在你为某一特定的源文件控制程序配置好选项后,BlackBerry IDE可以自动check out文件,运行预先设置的命令,恢复改变,以及增加新创建的文件到源文件控制程序里。
◆在BlackBerry IDE的File菜单,点击Edit->Preferences.
◆点击Source Control 标签。
◆点击Check out标签。
◆在Check out域,输入命令以能打开一个文件来编辑。例如输入:
p4 edit %1 |
(注:%1 参数代表了名称和一个文件的绝对路径。例如:对于一个在c:\mypath的foo.java文件,当BlackBerry IDE执行命令checkout %1,时,BlackBerry IDE实际上运行命令checkout c:\mypath\foo.java。)
◆点击Add file标签。
◆在Add new file域,输入命令以增加一个新的文件到源文件控制程序中。例如输入:
p4 add %1 |
◆点击 Revert file标签.
◆在Revert changes域,输入命令撤销一个源文件控制程序中的文件。例如输入:
p4 revert %1 |
◆单击OK。
编译项目
当你编译项目时,BlackBerry IDE编译你的源文件到Java 字节编码(Bytecode),进行预验证,然后将类打包为一个.cod文件。
(注:在Java ME中,字节编码验证分为2个步骤。已经编译的代码在它加载到BlackBerry设备之前预先验证,因此类加载时BlackBerry设备仅必须进行基本的验证。BlackBerry IDE在编译项目时自动进行预验证。)
当你编译一个项目时,如果需要,BlackBerry也编译项目依赖的任何库。
缺省的,已经编译的.cod文件使用项目名。为了改变这个名字,双击项目文件,点击Build标签,输入output file name(输出文件名)。
混淆应用程序
和传统的编译器不一样,BlackBerry平台的编译器因为受限的无线环境而优化了。在这里无线环境的目标是最小化应用程序的大小。作为结果的.cod文件提供了大量的类似于其他真正混淆包的混淆服务,以致能减小.cod文件本身的大小。例如,下面的信息将从.cod文件中移除:
所有调试的信息
本地变量名
源代码的行数
私有方法和成员名
同样,RIM相信没有必要为应用程序提供混淆,除了已经存在的BlackBerry平台编译的所有应用程序缺省提供的混淆。事实上,RIM没有对自己的产品进行任何额外的混淆。
对通过第三方工具混淆的支持没有集成到BlackBerry JDE .同样,需要一个命令行过程来混淆.cod文件供BlackBerry设备上使用。
混淆一个.cod文件
◆在BlackBerry IDE,创建应用程序
<--[if gte vml 1]> <![endif]--><--[if !vml]-->提示:在这个过程中将项目文件放到一个独立的目录中。
◆创建临时的目录
◆将BlackBerry IDE创建的jar文件拷贝到一个临时目录。
◆释放.jar文件的内容到一个临时目录。例如,在命令窗口输入下面的命令:*jar xvf SampleApplication.jar
◆删除释放为.jar文件部分的.cod文件。
◆删除.jar文件
◆混淆在临时目录下包含的类文件。
◆使用下面的命令对临时目录的内容运行预验证工具:
- *preverify.exe -verbose -d . -classpath ..\lib\net_rim_api.jar;
◆在已混淆(和预验证)的类文件上运行rapc来创建一个.cod文件。使用下面的命令:
- *rapc.exe -verbose import=..\lib\net_rim_api.jar listing=SampleApplication.lst codename=SampleApplication SampleApplication.rapc C:\yourTempDir\SampleApplication.class
生成API文档
使用一个BlackBerry IDE宏给代码加入注释。
一旦启用这个功能,如果你在一个函数声明前的任何一行输入/**,BlackBerry IDE生成下面的注释:
- /**
- * <description>.
- * @param menu <description>.
- * @param instance <description>.
- * @return <description>.
- */
- 如果你在其他行输入/**, the BlackBerry IDE 生成下面的注释::
- /**
- * <description>.
- */
BlackBerry IDE预先加载<description>.作为查询字符串,再查询第一个实例,然后选择这个实例,这个特性允许你输入描述,然后按F3转移到后面的参数。
因为javadocs宏依赖于分解浏览的信息,仅在成功完成一个编译后增加javadocs。如果你的文件包含一个语法错误,并且在上面你正试着插入注释,宏不会得到函数声明。
增加一个新的编辑器宏
◆在Edit菜单,点击Preferences。
◆点击Editor标签。
◆点击Macros按钮。
◆从When I type下拉列表中,选择/**.
◆在Replace it with文本框里,输入@javadoc.
◆在同一行或者每个函数声明的前一行输入/**。例如,在下面的代码段,在单词”protected”开头的插入点输入/**.
- /** protected int makeMenu(Menu menu, int instance) { ... }
#p#
使用命令行
BlackBerry JDE包含一个命令行编译器RAPC。RAPC编译.java和.jar文件到可以运行在BlackBerry设备模拟器或者加载到BlackBerry设备上的.cod文件。
Rapc.exe在BlackBerry JDE安装目录下的Bin下面。
RAPC接收下面的命令行选项。
#p#
使用蓝牙开发环境
为了利用狼牙开发环境使用BlackBerry设备模拟器,你需要从CSR(参看http://www.btdesigner.com/devcasira.htm)得到普通开发系统。
利用一个BlackBerry设备模拟器使用蓝牙开发环境
◆打开BlackBerry IDE
◆在主菜单,选择Edit>Preferences.
◆选择Simulator标签。
◆选择Ports标签。
◆在Communication port type域,选择合适的端口类型(参看Casira Endpoint文档)。
◆在Serial Port域,输入端口信息。
◆点击OK。#p#
使用Eclipse开发环境
Java调试有线协议(Java Debug Wire Protocol, JDWP)的程序为BlackBerry模拟器提供一个接口。当你启动JDWP时,你可以使用第三方集成的开发环境。
启动JDWP
>点击开始>程序>Research In Motion>BlackBerry JDE 4.1.0>JDWP.
(注:在启动JDWP之前,你必须从BlackBerry IDE启动BlackBerry设备模拟器至少一次。你仅需要启动JDWP一次。为了启动一个设备模拟器,在Eclipse开发环境中,点击Run>Debug.)
连接Eclipse开发环境
(注:在完成本节的任务之前,安装和配置Eclipse开发环境。)
完成下面的步骤:
◆扩展Sun JRE。
◆加入API文档。
◆设置Builder。
◆设置项目变量。
扩展Sun JRE
◆建立你的工作空间和项目。
◆启动Eclipse平台。
◆在Eclipse任务栏,点击Window>Preferences.
◆扩展Java项。
◆选择Installed JREs。
◆点击Add。
◆在Add JRE的窗口的JRE type域,选择Standard VM。
◆在JRE name域,为JRE输入一个名字。
◆在JRE home directory域,输入Sun JRE的位置。例如:
- C:\Java\jdk1.5.0_02\jre.
◆务必使Use default system libraries域没有选。
◆点击Add External JARs。
◆浏览你的BlackBerry IDE安装目录下的lib目录,例如:
- C:\Program Files\Research In Motion\BlackBerry JDE 4.1.0\lib
◆选择net_rim_api.jar.
◆点击Open。
加入API文档
◆加入RIM.jar到你的项目。
◆在Add JRE窗口,扩展net_rim_api.jar文件。
◆选择Javadoc location.
◆点击Edit。
◆点击Browser。
◆找到找到你的BlackBerry IDE目录下的docs\api目录。例如:
- C:\Program Files\Research In Motion\BlackBerry JDE 4.1.0\docs\api
◆点击OK。
◆点击OK。
◆在Installed JREs窗口,选择新创建的JRE,缺省的是RIM JVM。
◆在Add JRE窗口,点击OK。
设置Builder
◆在Eclipse任务栏,点击Project>Properties.
◆选择Builders。
◆点击New。
◆在Choose configuration type窗口,选择Program.
◆点击OK。
◆在New_Builder窗口属性的Name域,为你的Builder输入一个名字。
◆在Location域,点击Browser File System。
◆找到你的BlackBerry IDE目录下的Bin目录,例如:
- C:\Program Files\Research In Motion\BlackBerry JDE 4.1.0\bin
◆选择rapc.exe文件。
◆点击Open。
设置项目变量
◆在Working Directory域,点击Variables。
◆在Select Variable窗口,选择build project.
◆点击OK。
◆在Arguments域,输入:
- -quiet [desired space separated java, class, jar, or jad files] import=”C\Program Files\Research In Motion\BlackBerry JDE 4.1.0\lib\net_rim_api.jar” codename=C:\Development\ProjectName
例如:
- -quiet C:\Development\TestProject\*.java import=”C:\Program Files\Research In Motion\BlackBerry JDE 4.1.0\lib\net_rim_api.jar” codename=C:\Development\TestProject.
◆点击OK。
◆在New_Builder窗口属性里,点击Build Options标签。
◆在Run the builder部分,验证下面的选项是否选择了。
- After a “Clean”
- During manual builds
- During auto builds
◆点击OK。
◆在属性窗口,点击OK。
(注:RAPC不支持通配符,如果输入的路径发生错误,使用空格分隔文件列。例如将C:\Development\TestProject\*.java 代替为C:\Development\A.java C:\Development\B.java.)
设置连接时间
当在Eclipse开发环境里调试时,为了阻止连接超时,为正在调试的程序设置超时连接值。
◆在Eclipse的任务栏,点击Windows>Preferences.
◆扩展Java项。
◆选择Debug。
◆在Communication部分的Debugger timeout域,输入值。
◆在Launch timeout域输入值。
(注:你在Debugger timeout和Launch timeout设置的值依赖你的计算机处理速度。如果设置这些域之后连接问题继续出现,增加超时的值。)
使用Eclipse开发环境进行调试
◆在Eclipse点击Run>Debug.
◆选择Remote Java Application.
◆点击New。
◆点击Source标签。
◆确认你的程序是否列出。
◆点击Close。
◆打开JDWP程序,为了得到更多信息,参看27页的“启动JDWP“。
◆在Eclipse任务栏,点击Run>Debug.
◆在Remote Java Application项下面,选择一个应用程序。
◆点击Debug。
(注:如果出现下面的错误信息:“Failed to connect to remote VM. Connection timed out”,增加调试超时时间。为得到更多信息参看29页的”设置连接时间”.)#p#
编程指南
编写高效的代码,使用本地变量
不管什么时候,尽量使用本地变量。访问本地变量比访问类的成员高效。
使用速记判断Boolean条件
为了代替第一个例子中没有必要的判断Boolean条件,使用第二个例子中的速记。最后编译的代码会更短:
Java代码
- if( boolean_expression == true ) {
- return true;
- }
- else {
- return false;
- }
- // Do this
- return( boolean_expression );
使类为final
当你创建一个代码库时,如果你知道他们永远不会被扩展,那么将他们标记为final。final关键字的出现允许编译器生成更高效的代码。
(注:缺省,BlackBerry JDE编译器标记你应用程序.cod文件中不会扩展的类为final。)
使用int代替long
在Java中,一个long代表的是64位的整数。因为BlackBerry设备使用的是一个32位的处理器,如果你是用int代替long,操作将会快2-4倍。
避免垃圾回收
避免调用System.gc()进行垃圾回收。这个操作会占用许多时间,特别是在内存受限的BlackBerry设备上。让虚拟机进行垃圾回收。
对字符串使用静态变量
当定义String类型的静态字段(也成类字段),可以用静态变量(非final)代替常量(final)加快程序速度。反之,对于原始数据类型,例如int,也成立。
例如,你可能创建一个如下的String对象:
- private static final String x = "example";
对于这个静态常量(由final关键字标识),你使用常量的每个时候都会创建一个临时的String对象。在字节代码中,编译器去掉”x”,代替它的是字符串“example”,以致每次引用”x”时VM都会进行一次哈希表查询。
相比之下,度于静态变量(非final关键字),字符串只创建一次。仅当初始化“x”时,VM才进行哈希表查询。
(注:你可以使用公共常量(也就是final字段),但是标记变量为私有。)
避免String(String)的构造子
避免使用java.lang.String(String)构造子,因为它创建了一个没有必要的String对象,这个对象是作为参数提供的一个字符串的拷贝。因为String对象创建后不可以修改,所以拷贝典型没有必要。
(注:当使用字符串构造子时,编译器会由警告。)
- String str = new String("abc"); // 避免.
- String str = new String("found " + n + " items"); // 避免.
在Java程序里,每个引用的字符串都作为一个java.lang.String类的对象。换言之,你可以编写如下面的代码来创建一个String。
- String str = "abc"; // 建议.
- String str = "found " + n + " items"; // 建议.
编写有效的循环
在一个循环外考虑循环不变的代码。
- //避免
- for( int i = 0; i < vector.size(); i++ ) {
- ...
- }
在这个实现中,在每次的迭代中vector.size()被调用,这是低效的。如果你的容器可能不止一个元素,将容器的大小赋值给本地变量。下面的代码移除了循环不变的代码:
- // 建议
- int size = vector.size();
- for( int i = 0; i < size; ++i ) {
- ...
- }
另外,如果你迭代的项的顺序并不重要,你可以向后迭代来避免栈上多余的本地变量,并且可以使比较更加快速。
- for( int i = vector.size() - 1; i >= 0; --i ) {
- ...
- }
优化子表达式
假如你使用相同的表达式2次,不要依赖编译器为你优化。使用本地变量,如下代码:
- one( i+1 ); two( i+1 ); // Avoid.
- int tmp = i+1; one( tmp ); two( tmp ); // Prefer.
优化除法操作
除法操作在BlackBerry设备上可能慢,因为处理器没有硬件触发指令。
在你的代码中,当一个正数除以2时,使用向右移一位(>>1)代替.仅当你知道你正在处理的正数时使用“向右移位”(>>).
- midpoint = width / 2; // Avoid.
- int = width >> 1; // Prefer.
避免java.util.Enumeration
避免使用java.util.Enumeration对象,除非你想隐藏数据(换句话说,为了返回一个数据的枚举代替数据本身。
- // Avoid.
- for (Enumeration e = v.elements(); e.hasMoreElements();) {
- o = e.nextElement();
- ...
- }
为一个Enumeration对象请求一个向量或者哈希表速度慢,并且创建了不必要的垃圾。代替它的是,迭代元素本身,如下面的例子:
- // Prefer.
- for( int i = v.size() - 1; i >=0; --i ) {
- o = v.elementAt( i );
- ...
- }
如果向量可能被其他线程修改,同步迭代,如下例子所示:
- synchronized( v ) {
- for( int i = v.size() - 1; i >=0; --i ) {
- o = v.elementAt( i );
- ...
- }
- }
(注:Java SE使用一个Iterator对象实现类似的功能,但是iterator在Java ME不可用。)
使用instanceof进行转型
使用instanceof代替捕捉一个ClassCastException异常来判断转型是否成功。
- // Avoid.
- try
- {
- (String)x.whatever();
- }
- catch( ClassCastException e ) {
- ...
- }
- // Prefer.
- if( x instanceof String ) {
- (String)x.whatever();
- }
- else {
- ...
- }
使用instanceof比用try/catch要快。当转型失败发生异常时才使用try/catch。
在紧跟由一个instanceof检查的条件语句的第一个代码块里,BlackBerry IDE编译器和虚拟机被优化为仅对一个类检查。在由一个instanceof检查的条件语句后面的转型利用了这个优化。
例如,编译器可以优化第一个例子,但是第二个不能:
- // Prefer.
- if ( a instanceof <type> ) {
- <type> instance = (<type>)a;
- x.method(instance);
- instance.method(x, y, z);
- }
- // Avoid.
- if( a instanceof <type> ) {
- x.method( (<type>)a );
- }
使用instanceof判断条件
为了编写较小而快的代码,如果使用instanceof判断条件,不要显式判断一个变量是否为null。当”e”为null时,表达式e instanceof <type>判断为false。
- // Avoid.
- if( e != null && e instanceof ExampleClass ) {
- if( e == null || ! ( e instanceof ExampleClass)
- // Prefer.
- if( e instanceof ExampleClass ) { ... }
- if( ! ( e instanceof ExampleClass ) ) { ... }
避免使用StringBuffer.append(StringBuffer)
CLDC不包含StringBuilder.append(StringBuilder)方法。采用将一个string buffer加到另一个的方法会创建一个String的中间对象。代替它的是,应用程序可以使用net.rim.device.api.util.StringUtilities.append( StringBuffer dst, StringBuffer src[, int offset, int length ] ).
Java代码
- // Avoid.
- class outer {
- int i;
- class inner {
- inner() {}
- int example() { return i; }
- }
- }
比较而言,下面的代码仅仅定义了内部类名的范围:
- // Prefer.
- class outer {
- static class inner {
- ...
- }
- }
前一个例子是下面的缩写版本:
- class outer {
- ...
- }
- class outer$inner {
- ...
- }
当在内部类的方法里需要访问外部类数据时,仅仅使用一个非静态的内部类。如果为命名范围使用一个类,那么使这个类为static。
避免没有必要的初始化
在类里避免没有必要的字段初始化,这些类里,字段有缺省值。如果在一个类里没有初始化一个字段,它会自动使用下面的缺省值初始化字段。
◆对象引用初始化为null
◆int,byte或long初始化为0
◆boolean初始化为false
例如,下面的代码段没有不同:
Java代码
- // Avoid.
- class BadExample {
- private int fieldsCount = 0; // Avoid.
- private Field _fieldWithFocus = null; // Avoid.
- private boolean _validLayout = false; // Avoid.
- }
- // Prefer.
- class BetterExample {
- private int fieldsCount; // Prefer.
- private Field _fieldWithFocus; // Prefer.
- private boolean _validLayout; // Prefer.
- }
导入单独的类
一个应用程序仅使用了来自一个包的少量的类,这个程序应该导入单独的类,而不是整个库。
- // Avoid.
- import net.rim.blackberry.api.browser.*;
- // Prefer.
- import net.rim.blackberry.api.browser.Browser;
在BlackBerry设备上使用时间
在对时间敏感的应用程序里,不要为任何事物依赖时间区域,除了显示本地时间给用户。
BlackBerry 设备钟
BlackBerry设备操作系统从January 1, 1970 (UTC)的午夜以毫秒来计算绝对时间。时间一般以CPU周期或毫秒来计量的。
系统时间区域改变
如果因为性能原因正在缓存对时间敏感的对象,那么记住BlackBerry设备上的系统时间区域可能会改变。
当时间区域改变时,系统会发送一个全局的事件消息给应用程序。GlobalEventListener的实现,包括eventOccurred(),会接受这个事件。利用invoking Application.addGlobalEventListener()注册你的实现。
Java代码
- public void eventOccurred( long guid, int data0, int data1, Object object0,Object object1 ) {
- if( guid == DateTimeUtilities.GUID_TIMEZONE_CHANGED ) {
- _cal.setTimeZone( TimeZone.getDefault() );
- }
- }
决定手持设备上的网络时间
调用RadioInfo.GetNetworkTime(long deviceTime)得到以毫秒计量的对应网络报告时间,然后调整本地时间。deviceTime参数代表现在的毫秒级时间。
使用多线程
有效的利用BlackBerry操作系统多线程的能力。特殊地,为网络连接或长操作(大于0.1秒)创建线程。为监听者使用背后(Background)线程,或者当程序启动时使用在背后运行地其他进程。
最小化内存地使用
为了最小化运行时内存,使用下面地指南:
◆使用原始类型(如int或Boolean)代替对象(如String或Integer)。
◆不要全部依赖垃圾回收。避免快速地创建多个对象。当完成使用他们时,将对象引用设置为null。尽可能重用对象。
◆将大地操作一到Server上,例如,在发送数据到BlackBerry设备之前,完成对数据地过滤或排序。
避免返回null
如果你正在编写一个公共地方法返回一个对象,仅在下面地条件下它可以返回一个null:
◆在正常地程序运行期间,null对象时期望的。
◆Javadoc @return参数描述了null是一个可能的返回值。
如果一个null返回值不是正常期望的,那么程序将抛出一个合适的异常*调用者显式的处理这个问题。调用者不期望检验一个null的返回值,除非文档说明了。
避免传递null给方法
不要传递一个null参数给API方法,除非API引用显式说明了方法支持他们。
小心传递null参数给构造子
当传递null参数给构造子时,为了避免混淆,将null转化为合适的对象:
- new someObject ( (someObject)null );
如果一个类有两个或多个构造子,传递null参数可能不会唯一识别哪一个构造子将会使用。结果编译器会报错。在API参考里,并不是所有的构造子都会出现,因为有些构造子仅供内部使用。
通过转化null为合适的对象,你可以明确指明编译器会使用哪一个构造子。如果后续的API发行版本增加了新的构造子,它也可向前兼容。
使用long标记唯一标志符
使用一个long的标志符代替String标志符来标记唯一的常数,如GUID,哈希表键值,以及状态或上下文标志。
对于跨越第三方应用程序的标志符,为了保留其独立性,使用基于string生成的哈希生成的键值。在输入字符串里,包含了足够的信息提供唯一性。例如,使用一个完全信任的包名,如com.rim.samples.docs.helloworld。
转化一个string为long
◆在BlackBerry IDE文本编辑器里,输入一个字符串。
◆选择字符串。
◆右击字符串。
◆选择Convert”String” to Long.
正确退出应用程序
在调用System.exit(int status)之前,你的程序应该完成任何清理,例如移除在运行时存储的程序不在需要的对象。
打印栈跟踪(Stack trace)
当VM发现代码使用catch(Exception e)捕获异常时,VM优化为排除栈跟踪。如果捕获到Throwable,它不会排除栈跟踪。
例如,下面的代码不会排除栈跟踪:
- catch (IOException e) {
- e.printStackTrace()
- }
为了打印栈跟踪,编写类似下面的代码:
- catch (Throwable t) {
- t.printStackTrace();
- }
当你调试时为了查看栈跟踪,捕获一个Throwable实例。
好了,这便是我们为大家介绍的用Java语言编写BlackBerry应用程序。希望大家喜欢。
【编辑推荐】