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

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

定义一个构造子

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

Java代码

public HelloWorld() {  pushScreen(new HelloWorldScreen());}    
  • 1.

定义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;     
    
       }     
    
    }     
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.

#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, 20000010) {     
    
           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();     
    
    }    
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 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文件

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

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

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

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

*rapc.exe -verbose import=..\lib\net_rim_api.jar listing=SampleApplication.lst codename=SampleApplication SampleApplication.rapc C:\yourTempDir\SampleApplication.class 
  • 1.

生成API文档

使用一个BlackBerry IDE宏给代码加入注释。

一旦启用这个功能,如果你在一个函数声明前的任何一行输入/**,BlackBerry IDE生成下面的注释:

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

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) { ... } 
  • 1.

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

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

◆点击Add External JARs。

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

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

◆选择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  
  • 1.

◆点击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  
  • 1.

◆选择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 
  • 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. 
  • 1.

◆点击OK。

◆在New_Builder窗口属性里,点击Build Options标签。

◆在Run the builder部分,验证下面的选项是否选择了。

After a “Clean”   
During manual builds   
During auto builds  
  • 1.
  • 2.
  • 3.

◆点击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 );     
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 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对象:

private static final String x = "example"
  • 1.

对于这个静态常量(由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"); // 避免.  
  • 1.
  • 2.
  • 3.

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

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

编写有效的循环

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

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

  • 1.
  • 2.
  • 3.
  • 4.

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

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

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

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

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

  • 1.
  • 2.
  • 3.

优化子表达式

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

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

优化除法操作

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

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

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

避免java.util.Enumeration

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

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

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

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

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

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

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

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

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

(注: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 {  
...  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

使用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 );  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

使用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 ) ) { ... }  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

避免使用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; }     
    
       }     
    
    }     
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

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

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

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

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

当在内部类的方法里需要访问外部类数据时,仅仅使用一个非静态的内部类。如果为命名范围使用一个类,那么使这个类为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.     
    
    }     
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.

导入单独的类

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

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

在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() );     
    
           }     
    
       }     
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 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转化为合适的对象:

new someObject ( (someObject)null ); 
  • 1.

如果一个类有两个或多个构造子,传递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()  

  • 1.
  • 2.
  • 3.

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

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

  • 1.
  • 2.
  • 3.

当你调试时为了查看栈跟踪,捕获一个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 应用程序

2011-03-31 13:15:18

BlackBerry

2010-05-22 16:57:09

BlackBerry开

2010-09-10 08:32:45

android marApp CatalogApp Store

2024-01-15 00:42:55

Go语言应用程序

2023-09-22 09:41:28

LinuxC语言

2011-04-13 15:09:06

JavaBlackBerry

2010-06-12 16:41:10

BlackBerry开

2010-05-12 17:11:55

BlackBerry开

2012-09-06 11:18:17

IBMdw

2010-12-27 08:27:52

BlackBerry应用

2012-09-10 10:31:31

IBMdw

2011-06-07 09:10:41

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

2009-07-08 10:06:52

BlackBerry应

2014-01-07 10:12:15

Spark

2011-04-18 11:00:34

使用音频BlackBerry
点赞
收藏

51CTO技术栈公众号