天天看點

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

作者:Confach 發表于March 24,2006 18:05 pm 

版權資訊:可以任意轉載, 轉載時請務必以超連結形式标明文章原始出處和作者資訊. 

http://www.cnblogs.com/confach/articles/358028.html

2

第2章 編寫BlackBerry Java應用程式

應用程式管理

編寫一個例程

重用一般代碼

使用BlackBerry IDE

使用指令行

使用藍牙開發環境

使用Eclipse開發環境

程式設計指南

應用程式管理

當BlackBerry裝置啟動時,VM加載應用程式管理器,它管理在BlackBerry裝置上所有運作的程式。對于其他Java程式,應用程式管理器的功能類似作業系統事件的中心排程員一樣。

提供使用者界面的應用程式擴充了net.rim.device.api.ui.UiApplication類。這個類為應用程式提供方法來注冊事件監聽者,管理線程以及UI元件。

沒有提供使用者界面的應用程式擴充了net.rim.device.api.system.Application類。

BlackBerry應用程式開始于main()函數。當一個程式開始時,它的main()線程調用enterEventDispatcher()來開始處理事件。這個線程運作所有繪圖以及事件處理的代碼,以及登等待應用程式隊列裡地事件。

當應用程式管理器接收到一個事件時,它将這個事件拷貝到合适的隊列裡,這個隊列可以允許應用程式管理器指揮消息到特定的程式中。例如,前台的應用程式僅接收使用者輸入的消息。

編寫一個例程

擴充UiApplication基類

每個提供使用者接口的應用程式擴充了UiApplication基類,UiApplication類為應用程式定義了方法來建立一個事件線程,并且顯示和維護Screen對象。

定義 main()

在main()中,為應用程式建立一個新的對象。調用enterEventDispatcher()使應用程式進入事件線程并且開始處理消息。

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

定義一個構造子

為你的應用程式定義預設的構造子。預設的構造子調用UiApplication.pushScreen()以顯示當應用程式啟動時出現的螢幕。在本例中,螢幕使一個新的HelloWorldScreen執行個體,它在下節的代碼中定義:

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上下文菜單項。

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

例: HelloWorld.java

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;

       }

    }

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

重用一般代碼

抽象基類可以使你跨越多個類實作和重用一般功能。每個應用程式可以擴充單個基類。在BlackBerry IDE,加入基類到一個庫項目中。為每個應用程式建立一個獨立的項目,定義庫項目的依賴。

代碼執行個體

本指南的例程擴充了BaseApp類,它實作下面的功能:

  • 擴充UiApplication類
  • 實作KeyListener和TrackwheelListener接口
  • 定義變量,例如一般的菜單項
  • 定義一個方法建立應用程式菜單。
  • 為菜單選擇定義一個方法
  • 定義一個抽象方法退出程式

例: BaseApp.java

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

    public BaseApp() {

       _closeItem = new MenuItem(_resources, MENUITEM_CLOSE, 200000, 10) {

           public void run() {

              onExit();

              System.exit(0);

              }

           };

           }

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

       }

    public boolean trackwheelClick( int status, int time ) {

       Menu menu = new Menu();

       makeMenu( menu, 0);

       menu.show();

       return true;

       }

    public boolean trackwheelUnclick( int status, int time ) {

       return false;

       }

    public boolean trackwheelRoll(int amount, int status, int time) {

       return false;

       }

    public boolean keyChar(char key, int status, int time) {

       boolean retval = false;

       switch (key) {

       case Characters.ESCAPE:

           onExit();

           System.exit(0);

           retval = true;

           break;

           }

       return retval;

       }

    public boolean keyDown(int keycode, int time) {

       return false;

       }

    public boolean keyRepeat(int keycode, int time) {      

       return false;

       }

    public boolean keyStatus(int keycode, int time) {

       return false;

       }

    public boolean keyUp(int keycode, int time) {

       return false;

       }

    protected abstract void onExit();

    }

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

使用BlackBerry IDE

 為了編寫,調試和編譯應用程式,使用BlackBerry IDE,它是BlackBerry JDE的一部分。

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:BlackBerry 版本4.1使用了Sun JDK 5.0

建立一個工作空間

1.       在BlackBerry IDE,選擇File菜單,點選New Workspace

2.       在Workspace name域,輸入一個沒有檔案擴充名的名字。

3.       在Create in this directory域,輸入一個文檔。

4.       點選OK.

建立一個項目

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:在包含工作空間的檔案夾下的子目錄中建立工程。

1.  在BlackBerry IDE的Project菜單,點選Create New Project.

2.  在Project name域,輸入一個沒有檔案擴張名的項目名稱。

3.  在Create project in this directory域,輸入在此檔案夾下建立項目的檔案夾名稱。

4.  點選OK。

5.在工作空間檔案區域裡,輕按兩下項目名稱來設定項目屬性。

為了得到更多關于項目屬性的資訊,參看BlackBerry Integrated Development Environment Online Help。

建立源檔案

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:儲存源檔案到和項目檔案相同的檔案夾下。和所有Java程式一樣,為符合你的類使用的包層次關系的源代碼建立檔案結構,

1.  在BlackBerry IDE的File菜單,點選New。

2.  在Source file name域,輸入一個帶.java檔案擴充的檔案名。

3.  在Create source file in this directory域,輸入檔案夾名。

4.  點選OK。

5.  在編輯器區域,右擊檔案,然後點選Insert into project.

6.  選擇一個項目。

7.  點選OK。

和BlackBerry IDE內建源檔案管理工具

你可以通過不同的源檔案控制程式來使用BlackBerry IDE。BlackBerry IDE允許你為源檔案控制程式設定“check out”, “add new file”和“revert”選項。在你為某一特定的源檔案控制程式配置好選項後,BlackBerry IDE可以自動check out檔案,運作預先設定的指令,恢複改變,以及增加新建立的檔案到源檔案控制程式裡。

1.  在BlackBerry IDE的File菜單,點選Edit->Preferences.

2.  點選Source Control 标簽。

3.  點選Check out标簽。

4.  在Check out域,輸入指令以能打開一個檔案來編輯。例如輸入:

p4 edit %1

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:%1 參數代表了名稱和一個檔案的絕對路徑。例如:對于一個在c:/mypath的foo.java檔案,當BlackBerry IDE執行指令checkout %1,時,BlackBerry IDE實際上運作指令checkout c:/mypath/foo.java。

5.  點選Add file标簽。

6.  在Add new file域,輸入指令以增加一個新的檔案到源檔案控制程式中。例如輸入:

   p4 add %1

7. 點選 Revert file标簽.

8. 在Revert changes域,輸入指令撤銷一個源檔案控制程式中的檔案。例如輸入:

         p4 revert %1

9.-->單擊OK。

編譯項目

當你編譯項目時,BlackBerry IDE編譯你的源檔案到Java 位元組編碼(Bytecode),進行預驗證,然後将類打包為一個.cod檔案。

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:在Java ME中,位元組編碼驗證分為2個步驟。已經編譯的代碼在它加載到BlackBerry裝置之前預先驗證,是以類加載時BlackBerry裝置僅必須進行基本的驗證。BlackBerry IDE在編譯項目時自動進行預驗證。

當你編譯一個項目時,如果需要,BlackBerry也編譯項目依賴的任何庫。

動作 過程 附加資訊
編譯所有項目 > 在Build菜單,點選Build All 為了排除一個項目,設定項目屬性。
編譯所有活動的項目 > 在Build菜單,點選Build。 在工作空間,活動的項目名是加粗的。為了改變哪些項目是活動的,在Project菜單,點選Set Active Projects.
編譯單一項目
  1. 選擇一個項目
  2.    在 Build 菜單,點選 Build Selected 。
―――
建立一個工作空間makefile >在Build菜單,點選Generate Makefile and Resource. ―――

預設的,已經編譯的.cod檔案使用項目名。為了改變這個名字,輕按兩下項目檔案,點選Build标簽,輸入output file name(輸出檔案名)。

混淆應用程式

和傳統的編譯器不一樣,BlackBerry平台的編譯器因為受限的無線環境而優化了。在這裡無線環境的目标是最小化應用程式的大小。作為結果的.cod檔案提供了大量的類似于其他真正混淆包的混淆服務,以緻能減小.cod檔案本身的大小。例如,下面的資訊将從.cod檔案中移除:

  • 所有調試的資訊
  • 本地變量名
  • 源代碼的行數
  • 私有方法和成員名

同樣,RIM相信沒有必要為應用程式提供混淆,除了已經存在的BlackBerry平台編譯的所有應用程式預設提供的混淆。事實上,RIM沒有對自己的産品進行任何額外的混淆。

對通過第三方工具混淆的支援沒有內建到BlackBerry  JDE .同樣,需要一個指令行過程來混淆.cod檔案供BlackBerry裝置上使用。

混淆一個.cod檔案

1.  在BlackBerry IDE,建立應用程式

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

<--[if gte vml 1]> <![endif]--><--[if !vml]-->提示:在這個過程中将項目檔案放到一個獨立的目錄中。

2.  建立臨時的目錄

3.  将BlackBerry IDE建立的jar檔案拷貝到一個臨時目錄。

4.  釋放.jar檔案的内容到一個臨時目錄。例如,在指令視窗輸入下面的指令:*jar xvf SampleApplication.jar

5.  删除釋放為.jar檔案部分的.cod檔案。

6.  删除.jar檔案

7.  混淆在臨時目錄下包含的類檔案。

8.  使用下面的指令對臨時目錄的内容運作預驗證工具:

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

9.  在已混淆(和預驗證)的類檔案上運作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>.作為查詢字元串,再查詢第一個執行個體,然後選擇這個執行個體,這個特性允許你輸入描述,然後按F3轉移到後面的參數。

因為javadocs宏依賴于分解浏覽的資訊,僅在成功完成一個編譯後增加javadocs。如果你的檔案包含一個文法錯誤,并且在上面你正試着插入注釋,宏不會得到函數聲明。

增加一個新的編輯器宏

1.       在Edit菜單,點選Preferences。

2.       點選Editor标簽。

3.       點選Macros按鈕。

4.       從When I type下拉清單中,選擇/**.

5.       在Replace it with文本框裡,輸入@javadoc.

6.       在同一行或者每個函數聲明的前一行輸入/**。例如,在下面的代碼段,在單詞”protected”開頭的插入點輸入/**.

     /** protected int makeMenu(Menu menu, int instance) { ... }

使用指令行

BlackBerry JDE包含一個指令行編譯器RAPC。RAPC編譯.java和.jar檔案到可以運作在BlackBerry裝置模拟器或者加載到BlackBerry裝置上的.cod檔案。

Rapc.exe在BlackBerry JDE安裝目錄下的Bin下面。

RAPC接收下面的指令行選項。

選項 描述
import 指明RIM API和其他依賴的庫
codename 指明應用程式名(這典型是.jar檔案名)
midlet 指明應用程式是否是MIDlet
jad 指明JAD檔案名
/filename_1.java[附加.java檔案如果需要>] 指明.java檔案名,如果正在編譯java檔案。
/JAR_filename.jar 指明.jar檔案名,如果正在編譯一個,jar檔案。

使用藍牙開發環境

為了利用狼牙開發環境使用BlackBerry裝置模拟器,你需要從CSR(參看http://www.btdesigner.com/devcasira.htm)得到普通開發系統。

利用一個BlackBerry裝置模拟器使用藍牙開發環境

1.  打開BlackBerry IDE

2.  在主菜單,選擇Edit>Preferences.

3.  選擇Simulator标簽。

4.  選擇Ports标簽。

5.  在Communication port type域,選擇合适的端口類型(參看Casira Endpoint文檔)。

6.  在Serial Port域,輸入端口資訊。

7.  點選OK。

使用Eclipse開發環境

Java調試有線協定(Java Debug Wire Protocol, JDWP)的程式為BlackBerry模拟器提供一個接口。當你啟動JDWP時,你可以使用第三方內建的開發環境。

啟動JDWP

>點選開始>程式>Research In Motion>BlackBerry JDE 4.1.0>JDWP.

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:在啟動JDWP之前,你必須從BlackBerry IDE啟動BlackBerry裝置模拟器至少一次。你僅需要啟動JDWP一次。為了啟動一個裝置模拟器,在Eclipse開發環境中,點選Run>Debug.

連接配接Eclipse開發環境

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:在完成本節的任務之前,安裝和配置Eclipse開發環境。

完成下面的步驟:

1.         擴充Sun JRE。

2.         加入API文檔。

3.         設定Builder。

4.         設定項目變量。

擴充Sun JRE

1.         建立你的工作空間和項目。

2.         啟動Eclipse平台。

3.         在Eclipse工作列,點選Window>Preferences.

4.         擴充Java項。

5.         選擇Installed JREs。

6.         點選Add。

7.         在Add JRE的視窗的JRE type域,選擇Standard VM。

8.         在JRE name域,為JRE輸入一個名字。

9.         在JRE home directory域,輸入Sun JRE的位置。例如:

       C:/Java/jdk1.5.0_02/jre.

10.     務必使Use default system libraries域沒有選。

11.     點選Add External JARs。

12.     浏覽你的BlackBerry IDE安裝目錄下的lib目錄,例如:

   C:/Program Files/Research In Motion/BlackBerry JDE 4.1.0/lib

13.     選擇net_rim_api.jar.

14.     點選Open。

加入API文檔

1.         加入RIM.jar到你的項目。

2.         在Add JRE視窗,擴充net_rim_api.jar檔案。

3.         選擇Javadoc location.

4.         點選Edit。

5.         點選Browser。

6.         找到找到你的BlackBerry IDE目錄下的docs/api目錄。例如:

   C:/Program Files/Research In Motion/BlackBerry JDE 4.1.0/docs/api

7.         點選OK。

8.         點選OK。

9.         在Installed JREs視窗,選擇新建立的JRE,預設的是RIM JVM。

10.      在Add JRE視窗,點選OK。

設定Builder

1.         在Eclipse工作列,點選Project>Properties.

2.         選擇Builders。

3.         點選New。

4.         在Choose configuration type視窗,選擇Program.

5.         點選OK。

6.         在New_Builder視窗屬性的Name域,為你的Builder輸入一個名字。

7.         在Location域,點選Browser File System。

8.         找到你的BlackBerry IDE目錄下的Bin目錄,例如:

 C:/Program Files/Research In Motion/BlackBerry JDE 4.1.0/bin

9.         選擇rapc.exe檔案。

10.     點選Open。

設定項目變量

1.         在Working Directory域,點選Variables。

2.         在Select Variable視窗,選擇build project.

3.         點選OK。

4.         在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.

5.         點選OK。

6.         在New_Builder視窗屬性裡,點選Build Options标簽。

7.         在Run the builder部分,驗證下面的選項是否選擇了。

  •  After a “Clean”
  • During manual builds
  • During auto builds

8.         點選OK。

9.         在屬性視窗,點選OK。

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:RAPC不支援通配符,如果輸入的路徑發生錯誤,使用空格分隔檔案列。例如将C:/Development/TestProject/*.java 代替為

C:/Development/A.java C:/Development/B.java.

設定連接配接時間

當在Eclipse開發環境裡調試時,為了阻止連接配接逾時,為正在調試的程式設定逾時連接配接值。

1.         在Eclipse的工作列,點選Windows>Preferences.

2.         擴充Java項。

3.         選擇Debug。

4.         在Communication部分的Debugger timeout域,輸入值。

5.         在Launch timeout域輸入值。

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:你在Debugger timeout和Launch timeout設定的值依賴你的計算機處理速度。如果設定這些域之後連接配接問題繼續出現,增加逾時的值。

使用Eclipse開發環境進行調試

1.         在Eclipse點選Run>Debug.

2.         選擇Remote Java Application.

3.         點選New。

4.         點選Source标簽。

5.         确認你的程式是否列出。

6.         點選Close。

7.         打開JDWP程式,為了得到更多資訊,參看27頁的“啟動JDWP“。

8.         在Eclipse工作列,點選Run>Debug.

9.         在Remote Java Application項下面,選擇一個應用程式。

10.     點選Debug。

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:如果出現下面的錯誤資訊:“Failed to connect to remote VM. Connection timed out”,增加調試逾時時間。為得到更多資訊參看29頁的”設定連接配接時間”.

程式設計指南

編寫高效的代碼

使用本地變量

不管什麼時候,盡量使用本地變量。通路本地變量比通路類的成員高效。

使用速記判斷Boolean條件

為了代替第一個例子中沒有必要的判斷Boolean條件,使用第二個例子中的速記。最後編譯的代碼會更短:

if( boolean_expression == true ) {

    return true;

    }

else {

    return false;

 }

// Do this

return( boolean_expression );

使類為final

 當你建立一個代碼庫時,如果你知道他們永遠不會被擴充,那麼将他們标記為final。final關鍵字的出現允許編譯器生成更高效的代碼。

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:預設,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才進行哈希表查詢。

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

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

避免String(String)的構造子

避免使用java.lang.String(String)構造子,因為它建立了一個沒有必要的String對象,這個對象是作為參數提供的一個字元串的拷貝。因為String對象建立後不可以修改,是以拷貝典型沒有必要。

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:當使用字元串構造子時,編譯器會由警告。

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

       ...

       }

}

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注: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 ] ).

// Avoid.

public synchronized StringBuffer append(Object obj) {

    return append(String.valueOf(obj));

}

// Prefer.

public synchronized StringBuffer append(Object obj) {

    if (obj instanceof StringBuffer) {

       StringBuffer sb = (StringBuffer)obj;

       net.rim.device.api.util.StringUtilities.append( this, sb, 0, sb )

       return this;

}

return append(String.valueOf(obj));

}

減小代碼大小

當編寫應用程式時可以采用下面的指南來減小編譯後代碼的大小。

設定适合的通路方式

當你建立代碼庫時,為字段和方法使用合适的通路權限可以顯著減小編譯後代碼的大小。特殊的是,完成以下操作:

l         不管什麼時候,隻要可能就将字段聲明為private。除了好的編碼實踐外,這可以使編譯器優化.cod檔案。

l         當可能時,使用預設(包)的通路方式來代替public通路(也就是,忽略public和protected關鍵字)

避免建立接口

當建立API庫時,避免建立接口,除非你預知API的多個實作。接口會産生更大更慢的代碼。

使用内部的靜态類

當建立一個内部的類隐藏一個在其他類裡的類時,但是内部類沒有引用外部類對象,聲明這個内部類為static。這個操作壓縮了對外部類引用的建立。

例如,下面的代碼需要一個對外部類對象的引用。

// Avoid.

class outer {

    int i;

    class inner {

       inner() {}

       int example() { return i; }

       }

    }

比較而言,下面的代碼僅僅定義了内部類名的範圍:

// Prefer.

class outer {

    static class inner {

       ...

    }

}

前一個例子是下面的縮寫版本:

class outer {

...

}

class outer$inner {

...

}

當在内部類的方法裡需要通路外部類資料時,僅僅使用一個非靜态的内部類。如果為命名範圍使用一個類,那麼使這個類為static。

避免沒有必要的初始化

在類裡避免沒有必要的字段初始化,這些類裡,字段有預設值。如果在一個類裡沒有初始化一個字段,它會自動使用下面的預設值初始化字段。

l         對象引用初始化為null

l         int,byte或long初始化為0

l         boolean初始化為false

例如,下面的代碼段沒有不同:

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

    }

第2章 編寫BlackBerry Java應用程式第2章 編寫BlackBerry Java應用程式

注:在一個方法裡,必須顯式初始化本地變量。

導入單獨的類

 一個應用程式僅使用了來自一個包的少量的類,這個程式應該導入單獨的類,而不是整個庫。

// 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()注冊你的實作。

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

1.      在BlackBerry IDE文本編輯器裡,輸入一個字元串。

2.      選擇字元串。

3.      右擊字元串。

4.      選擇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執行個體。

Last Updated:2007-01-05

Last Updated:2006-12-30

Last Updated:2006-03-24