Java语言编写BlackBerry应用程序

移动开发
本文我们将从BlackBerry应用程序管理、使用BlackBerry IDE和BlackBerry应用编程指南等八个方面为大家介绍如何使用Java语言编写BlackBerry应用程序。

BlackBerry手机在美国的企业级领域占有非常重要的地位,前不久我们为大家介绍过《BlackBerry应用程序开发方法》,本文我们将为大家介绍如何使用Java语言编写BlackBerry应用程序。

[[21004]]

应用程序管理

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代码

  1. public static void main(String[] args) {  HelloWorld theApp = new HelloWorld();  theApp.enterEventDispatcher();}   

定义一个构造子

为你的应用程序定义缺省的构造子。缺省的构造子调用UiApplication.pushScreen()以显示当应用程序启动时出现的屏幕。在本例中,屏幕使一个新的HelloWorldScreen实例,它在下节的代码中定义:

Java代码

  1. 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代码

  1.  
  2.  
  3. 例: HelloWorld.java     
  4.     
  5. /**    
  6.  *  HelloWorld.java    
  7.  *  Copyright (C) 2001-2005 Research In Motion Limited. All rights reserved.    
  8.  */    
  9.     
  10.       
  11.     
  12. package com.rim.samples.docs.helloworld;     
  13.     
  14. import net.rim.device.api.ui.*;     
  15.     
  16. import net.rim.device.api.ui.component.*;     
  17.     
  18. import net.rim.device.api.ui.container.*;     
  19.     
  20. import net.rim.device.api.system.*;     
  21.     
  22. import com.rim.samples.docs.resource.*;     
  23.     
  24.       
  25.     
  26. public class HelloWorld extends UiApplication {     
  27.     
  28.     public static void main(String[] args) {     
  29.     
  30.        HelloWorld theApp = new HelloWorld();     
  31.     
  32.        theApp.enterEventDispatcher();     
  33.     
  34.        }     
  35.     
  36.         
  37.     
  38.     public HelloWorld() {     
  39.     
  40.        pushScreen(new HelloWorldScreen());     
  41.     
  42.        }     
  43.     
  44.     }     
  45.     
  46.       
  47.     
  48.       
  49.     
  50. final class HelloWorldScreen extends MainScreen {     
  51.     
  52.     public HelloWorldScreen() {     
  53.     
  54.        super();     
  55.     
  56.         LabelField title = new LabelField(“HelloWorld Sample”, LabelField.ELLIPSIS     
  57.     
  58.                                          | LabelField.USE_ALL_WIDTH);     
  59.     
  60.        setTitle(title);     
  61.     
  62.        add(new RichTextField(“Hello World!”));     
  63.     
  64.        }     
  65.     
  66.            
  67.     
  68.     public boolean onClose() {     
  69.     
  70.        Dialog.alert(“Goodbye!”);     
  71.     
  72.        System.exit(0);     
  73.     
  74.        return true;     
  75.     
  76.        }     
  77.     
  78.     }     
  79.  

#p#

重用一般代码

抽象基类可以使你跨越多个类实现和重用一般功能。每个应用程序可以扩展单个基类。在BlackBerry IDE,加入基类到一个库项目中。为每个应用程序创建一个独立的项目,定义库项目的依赖。

代码实例

◆本指南的例程扩展了BaseApp类,它实现下面的功能:

◆扩展UiApplication类

◆实现KeyListener和TrackwheelListener接口

◆定义变量,例如一般的菜单项

定义一个方法创建应用程序菜单。

◆为菜单选择定义一个方法

◆定义一个抽象方法退出程序

Java代码

  1.  
  2.  
  3. 例: BaseApp.java     
  4.     
  5. /*    
  6.  * * BaseApp.java    
  7.  * * Copyright (C) 2001-2005 Research In Motion Limited. All rights reserved.    
  8.  * */    
  9.     
  10.       
  11.     
  12.       
  13.     
  14. package com.rim.samples.docs.baseapp;     
  15.     
  16. import net.rim.device.api.i18n.*;     
  17.     
  18. import net.rim.device.api.system.*;     
  19.     
  20. import net.rim.device.api.ui.container.*;     
  21.     
  22. import net.rim.device.api.ui.*;     
  23.     
  24. import net.rim.device.api.ui.component.*;     
  25.     
  26. import com.rim.samples.docs.resource.*;     
  27.     
  28.       
  29.     
  30. public abstract class BaseApp     
  31.     
  32.    extends UiApplication implements BaseAppResource, KeyListener, TrackwheelListener {     
  33.     
  34.     private MenuItem _closeItem;     
  35.     
  36.     private static ResourceBundle _resources =     
  37.     
  38.        ResourceBundle.getBundle(BUNDLE_ID, BUNDLE_NAME);     
  39.     
  40.         
  41.     
  42.         
  43.     
  44.     /* Constructor for the abstract base class. */    
  45.     
  46.     public BaseApp() {     
  47.     
  48.        _closeItem = new MenuItem(_resources, MENUITEM_CLOSE, 20000010) {     
  49.     
  50.            public void run() {     
  51.     
  52.               onExit();     
  53.     
  54.               System.exit(0);     
  55.     
  56.               }     
  57.     
  58.            };     
  59.     
  60.            }     
  61.     
  62.         
  63.     
  64.     /* Override this method to add custom menu items. */    
  65.     
  66.     protected void makeMenu( Menu menu, int instance) {     
  67.     
  68.        Field focus = UiApplication.getUiApplication().     
  69.     
  70.                      getActiveScreen().getLeafFieldWithFocus();     
  71.     
  72.            
  73.     
  74.        if(focus != null) {     
  75.     
  76.            ContextMenu contextMenu = focus.getContextMenu();     
  77.     
  78.            if( !contextMenu.isEmpty()) {     
  79.     
  80.               menu.add(contextMenu);     
  81.     
  82.               menu.addSeparator();     
  83.     
  84.               }     
  85.     
  86.            }     
  87.     
  88.        menu.add(_closeItem);     
  89.     
  90.        }     
  91.     
  92.         
  93.     
  94.     /* Invoked when the trackwheel is clicked. */    
  95.     
  96.     public boolean trackwheelClick( int status, int time ) {     
  97.     
  98.        Menu menu = new Menu();     
  99.     
  100.        makeMenu( menu, 0);     
  101.     
  102.        menu.show();     
  103.     
  104.        return true;     
  105.     
  106.        }     
  107.     
  108.         
  109.     
  110.     /* Invoked when the trackwheel is released. */    
  111.     
  112.     public boolean trackwheelUnclick( int status, int time ) {     
  113.     
  114.        return false;     
  115.     
  116.        }     
  117.     
  118.         
  119.     
  120.     /* Invoked when the trackwheel is rolled. */    
  121.     
  122.     public boolean trackwheelRoll(int amount, int status, int time) {     
  123.     
  124.        return false;     
  125.     
  126.        }     
  127.     
  128.         
  129.     
  130.     public boolean keyChar(char key, int status, int time) {     
  131.     
  132.        /* Intercept the ESC key and exit the application. */    
  133.     
  134.        boolean retval = false;     
  135.     
  136.        switch (key) {     
  137.     
  138.        case Characters.ESCAPE:     
  139.     
  140.            onExit();     
  141.     
  142.            System.exit(0);     
  143.     
  144.            retval = true;     
  145.     
  146.            break;     
  147.     
  148.            }     
  149.     
  150.        return retval;     
  151.     
  152.        }     
  153.     
  154.         
  155.     
  156.     /* Implementation of KeyListener.keyDown(). */    
  157.     
  158.     public boolean keyDown(int keycode, int time) {     
  159.     
  160.        return false;     
  161.     
  162.        }     
  163.     
  164.         
  165.     
  166.     /* Implementation of KeyListener.keyRepeat(). */    
  167.     
  168.     public boolean keyRepeat(int keycode, int time) {           
  169.     
  170.        return false;     
  171.     
  172.        }     
  173.     
  174.         
  175.     
  176.         
  177.     
  178.     /* Implementation of KeyListener.keyStatus(). */    
  179.     
  180.     public boolean keyStatus(int keycode, int time) {     
  181.     
  182.        return false;     
  183.     
  184.        }     
  185.     
  186.         
  187.     
  188. /* Implementation of KeyListener.keyUp(). */    
  189.     
  190.     public boolean keyUp(int keycode, int time) {     
  191.     
  192.        return false;     
  193.     
  194.        }     
  195.     
  196.         
  197.     
  198.     protected abstract void onExit();     
  199.     
  200.     }    
  201.  

#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文件

◆混淆在临时目录下包含的类文件。

◆使用下面的命令对临时目录的内容运行预验证工具:

  1. *preverify.exe -verbose -d . -classpath ..\lib\net_rim_api.jar; 

◆在已混淆(和预验证)的类文件上运行rapc来创建一个.cod文件。使用下面的命令:

  1. *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生成下面的注释:

  1. /**  
  2. * <description>.  
  3. * @param menu <description>.  
  4. * @param instance <description>.  
  5. * @return <description>.  
  6. */ 
  7. 如果你在其他行输入/**, the BlackBerry IDE 生成下面的注释::  
  8. /**  
  9. * <description>.  
  10. */ 

BlackBerry IDE预先加载<description>.作为查询字符串,再查询第一个实例,然后选择这个实例,这个特性允许你输入描述,然后按F3转移到后面的参数。

因为javadocs宏依赖于分解浏览的信息,仅在成功完成一个编译后增加javadocs。如果你的文件包含一个语法错误,并且在上面你正试着插入注释,宏不会得到函数声明。

增加一个新的编辑器宏

◆在Edit菜单,点击Preferences。

◆点击Editor标签。

◆点击Macros按钮。

◆从When I type下拉列表中,选择/**.

◆在Replace it with文本框里,输入@javadoc.

◆在同一行或者每个函数声明的前一行输入/**。例如,在下面的代码段,在单词”protected”开头的插入点输入/**.

  1. /** 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的位置。例如:

  1. C:\Java\jdk1.5.0_02\jre. 

◆务必使Use default system libraries域没有选。

◆点击Add External JARs。

◆浏览你的BlackBerry IDE安装目录下的lib目录,例如:

  1. 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目录。例如:

  1. 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目录,例如:

  1. C:\Program Files\Research In Motion\BlackBerry JDE 4.1.0\bin  

◆选择rapc.exe文件。

◆点击Open。

设置项目变量

◆在Working Directory域,点击Variables。

◆在Select Variable窗口,选择build project.

◆点击OK。

◆在Arguments域,输入:

  1. -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 

例如:

  1. -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部分,验证下面的选项是否选择了。

  1. After a “Clean”   
  2. During manual builds   
  3. 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代码

  1.  
  2.  
  3. if( boolean_expression == true ) {     
  4.     
  5.     return true;     
  6.     
  7.     }     
  8.     
  9. else {     
  10.     
  11.     return false;     
  12.     
  13.  }     
  14.     
  15. // Do this     
  16.     
  17. return( boolean_expression );     
  18.  

使类为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对象:

  1. private static final String x = "example"

对于这个静态常量(由final关键字标识),你使用常量的每个时候都会创建一个临时的String对象。在字节代码中,编译器去掉”x”,代替它的是字符串“example”,以致每次引用”x”时VM都会进行一次哈希表查询。

相比之下,度于静态变量(非final关键字),字符串只创建一次。仅当初始化“x”时,VM才进行哈希表查询。

(注:你可以使用公共常量(也就是final字段),但是标记变量为私有。)

避免String(String)的构造子

避免使用java.lang.String(String)构造子,因为它创建了一个没有必要的String对象,这个对象是作为参数提供的一个字符串的拷贝。因为String对象创建后不可以修改,所以拷贝典型没有必要。

(注:当使用字符串构造子时,编译器会由警告。)

  1. String str = new String("abc"); // 避免.  
  2.  
  3. String str = new String("found " + n + " items"); // 避免.  

在Java程序里,每个引用的字符串都作为一个java.lang.String类的对象。换言之,你可以编写如下面的代码来创建一个String。

  1. String str = "abc"// 建议.  
  2.  
  3. String str = "found " + n + " items"// 建议.  

编写有效的循环

在一个循环外考虑循环不变的代码。

  1. //避免  
  2. forint i = 0; i < vector.size(); i++ ) {  
  3. ...  

在这个实现中,在每次的迭代中vector.size()被调用,这是低效的。如果你的容器可能不止一个元素,将容器的大小赋值给本地变量。下面的代码移除了循环不变的代码:

  1. // 建议  
  2. int size = vector.size();  
  3. forint i = 0; i < size; ++i ) {  
  4. ...  

另外,如果你迭代的项的顺序并不重要,你可以向后迭代来避免栈上多余的本地变量,并且可以使比较更加快速。

  1. forint i = vector.size() - 1; i >= 0; --i ) {  
  2. ...  

优化子表达式

假如你使用相同的表达式2次,不要依赖编译器为你优化。使用本地变量,如下代码:

  1. one( i+1 ); two( i+1 ); // Avoid.  
  2. int tmp = i+1; one( tmp ); two( tmp ); // Prefer. 

优化除法操作

除法操作在BlackBerry设备上可能慢,因为处理器没有硬件触发指令。

在你的代码中,当一个正数除以2时,使用向右移一位(>>1)代替.仅当你知道你正在处理的正数时使用“向右移位”(>>).

  1. midpoint = width / 2// Avoid.  
  2. int = width >> 1// Prefer. 

避免java.util.Enumeration

避免使用java.util.Enumeration对象,除非你想隐藏数据(换句话说,为了返回一个数据的枚举代替数据本身。

  1. // Avoid.  
  2. for (Enumeration e = v.elements(); e.hasMoreElements();) {  
  3. o = e.nextElement();  
  4. ...  

为一个Enumeration对象请求一个向量或者哈希表速度慢,并且创建了不必要的垃圾。代替它的是,迭代元素本身,如下面的例子:

  1. // Prefer.  
  2. forint i = v.size() - 1; i >=0; --i ) {  
  3. o = v.elementAt( i );  
  4. ...  

如果向量可能被其他线程修改,同步迭代,如下例子所示:

  1. synchronized( v ) {  
  2.     forint i = v.size() - 1; i >=0; --i ) {  
  3.        o = v.elementAt( i );  
  4.        ...  
  5.        }  

(注:Java SE使用一个Iterator对象实现类似的功能,但是iterator在Java ME不可用。)
 
使用instanceof进行转型

使用instanceof代替捕捉一个ClassCastException异常来判断转型是否成功。

  1. // Avoid.  
  2. try 
  3. {  
  4.     (String)x.whatever();  
  5.     }  
  6. catch( ClassCastException e ) {  
  7.        ...  
  8. }  
  9.    
  10. // Prefer.  
  11. if( x instanceof String ) {  
  12.     (String)x.whatever();  
  13.     }  
  14. else {  
  15. ...  

使用instanceof比用try/catch要快。当转型失败发生异常时才使用try/catch。

在紧跟由一个instanceof检查的条件语句的第一个代码块里,BlackBerry IDE编译器和虚拟机被优化为仅对一个类检查。在由一个instanceof检查的条件语句后面的转型利用了这个优化。

例如,编译器可以优化第一个例子,但是第二个不能:

  1. // Prefer.  
  2. if ( a instanceof <type> ) {  
  3.     <type> instance = (<type>)a;  
  4.     x.method(instance);  
  5.     instance.method(x, y, z);  
  6. }  
  7.    
  8. // Avoid.  
  9. if( a instanceof <type> ) {  
  10.     x.method( (<type>)a );  

使用instanceof判断条件

为了编写较小而快的代码,如果使用instanceof判断条件,不要显式判断一个变量是否为null。当”e”为null时,表达式e instanceof <type>判断为false。

  1.  
  2.  
  3. // Avoid.  
  4. if( e != null && e instanceof ExampleClass ) {  
  5. if( e == null || ! ( e instanceof ExampleClass)  
  6.        
  7. // Prefer.  
  8. if( e instanceof ExampleClass ) { ... }  
  9. 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代码

  1.  
  2.  
  3. // Avoid.     
  4.     
  5. class outer {     
  6.     
  7.     int i;     
  8.     
  9.     class inner {     
  10.     
  11.        inner() {}     
  12.     
  13.        int example() { return i; }     
  14.     
  15.        }     
  16.     
  17.     }     
  18.  

比较而言,下面的代码仅仅定义了内部类名的范围:

  1.  
  2.  
  3. // Prefer.  
  4. class outer {  
  5.     static class inner {  
  6.        ...  
  7.     }  
  8. }  
  9.  

前一个例子是下面的缩写版本:

  1.  
  2.  
  3. class outer {  
  4. ...  
  5. }  
  6. class outer$inner {  
  7. ...  
  8. }  
  9.  

当在内部类的方法里需要访问外部类数据时,仅仅使用一个非静态的内部类。如果为命名范围使用一个类,那么使这个类为static。

避免没有必要的初始化

在类里避免没有必要的字段初始化,这些类里,字段有缺省值。如果在一个类里没有初始化一个字段,它会自动使用下面的缺省值初始化字段。

◆对象引用初始化为null

◆int,byte或long初始化为0

◆boolean初始化为false

例如,下面的代码段没有不同:

Java代码

  1.  
  2.  
  3. // Avoid.     
  4.     
  5. class BadExample {     
  6.     
  7.     private int fieldsCount = 0// Avoid.     
  8.     
  9.     private Field _fieldWithFocus = null// Avoid.     
  10.     
  11.     private boolean _validLayout = false// Avoid.     
  12.     
  13.     }     
  14.     
  15.       
  16.     
  17. // Prefer.     
  18.     
  19. class BetterExample {     
  20.     
  21.     private int fieldsCount; // Prefer.     
  22.     
  23.     private Field _fieldWithFocus; // Prefer.     
  24.     
  25.     private boolean _validLayout; // Prefer.     
  26.     
  27.     }     
  28.  

导入单独的类

 一个应用程序仅使用了来自一个包的少量的类,这个程序应该导入单独的类,而不是整个库。

  1. // Avoid.  
  2. import net.rim.blackberry.api.browser.*;  
  3.    
  4. // Prefer.  
  5. import net.rim.blackberry.api.browser.Browser; 

在BlackBerry设备上使用时间

在对时间敏感的应用程序里,不要为任何事物依赖时间区域,除了显示本地时间给用户。

BlackBerry 设备钟

BlackBerry设备操作系统从January 1, 1970 (UTC)的午夜以毫秒来计算绝对时间。时间一般以CPU周期或毫秒来计量的。

系统时间区域改变

如果因为性能原因正在缓存对时间敏感的对象,那么记住BlackBerry设备上的系统时间区域可能会改变。

当时间区域改变时,系统会发送一个全局的事件消息给应用程序。GlobalEventListener的实现,包括eventOccurred(),会接受这个事件。利用invoking Application.addGlobalEventListener()注册你的实现。

Java代码

  1.  
  2.  
  3. public void eventOccurred( long guid, int data0, int data1, Object object0,Object object1 ) {     
  4.     
  5.        if( guid == DateTimeUtilities.GUID_TIMEZONE_CHANGED ) {     
  6.     
  7.            _cal.setTimeZone( TimeZone.getDefault() );     
  8.     
  9.            }     
  10.     
  11.        }     
  12.  

决定手持设备上的网络时间

调用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转化为合适的对象:

  1. 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,它不会排除栈跟踪。

例如,下面的代码不会排除栈跟踪:

  1. catch (IOException e) {  
  2.     e.printStackTrace()  

为了打印栈跟踪,编写类似下面的代码:

  1. catch (Throwable t) {  
  2.     t.printStackTrace();  

当你调试时为了查看栈跟踪,捕获一个Throwable实例。

好了,这便是我们为大家介绍的用Java语言编写BlackBerry应用程序。希望大家喜欢。

【编辑推荐】

  1. 简介BlackBerry Mobile数据系统
  2. RIM应用开发入门 安装BlackBerry 6.0 SDK
  3. 简介BlackBerry应用程序开发方法
  4. RIM路线图:BlackBerry 7今年11月公布
  5. RIM即将发布新一代Blackberry操作系统
责任编辑:佚名 来源: 10086
相关推荐

2011-06-07 09:36:41

BlackBerry 应用程序

2010-05-22 16:57:09

BlackBerry开

2011-03-31 13:15:18

BlackBerry

2010-09-10 08:32:45

android marApp CatalogApp Store

2023-09-22 09:41:28

LinuxC语言

2024-01-15 00:42:55

Go语言应用程序

2011-04-13 15:09:06

JavaBlackBerry

2010-06-12 16:41:10

BlackBerry开

2010-05-12 17:11:55

BlackBerry开

2012-09-10 10:31:31

IBMdw

2012-09-06 11:18:17

IBMdw

2011-06-07 09:10:41

BlackBerry 开发

2010-12-27 08:27:52

BlackBerry应用

2018-06-22 09:00:00

Java框架Pronghorn

2011-07-12 10:59:41

JAVA多线程

2012-03-20 09:20:40

Go语言

2011-01-28 09:12:53

jQuery Mobi

2011-04-18 11:00:34

使用音频BlackBerry

2009-07-08 10:06:52

BlackBerry应

2010-11-18 15:52:32

QMLMeeGo
点赞
收藏

51CTO技术栈公众号