首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

J2ME RMS 實戰封裝:BaseRMS 抽象層與 Score 高分系統完整實現

     編輯:J2ME

前言:RecordStore 直接用太痛苦,封裝才是王道

J2ME RecordStore 僅提供位元組陣列 byte[] 的增刪改查,開發者需自行處理:

  • 物件 ↔ 位元組序列化(DataInput/OutputStream)
  • 記錄版本管理與預設資料初始化
  • 異常捕獲與資源關閉
  • 多執行緒同步(MIDlet Suite 共享)

本文展示一套生產級封裝模式:BaseRMS 抽象基類 + Score 具體實現,解決上述所有痛點。

BaseRMS:通用記錄存儲協議

abstract public class BaseRMS {
    private String rmsName;
    private RecordStore recordStore;

    BaseRMS(String rmsName) { this.rmsName = rmsName; }

    // 開啟:失敗則重建,有資料則載入,無則建立預設
    public void open() throws Exception {
        try {
            recordStore = RecordStore.openRecordStore(rmsName, true);
            if (recordStore.getNumRecords() > 0) loadData();
            else createDefaultData();
        } catch (Exception e) { throw new Exception(rmsName + "::open::" + e); }
    }

    public void close() throws Exception {
        if (recordStore != null) {
            try { recordStore.closeRecordStore(); }
            catch (Exception e) { throw new Exception(rmsName + "::close::" + e); }
        }
    }

    public RecordStore getRecordStore() { return recordStore; }
    public String getRMSName() { return rmsName; }

    // 子類必須實現:序列化/反序列化/預設值
    abstract void loadData() throws Exception;
    abstract void createDefaultData() throws Exception;
    abstract void updateData() throws Exception;
}

關鍵設計決策

  1. 模板方法模式: open() 定義標準流程,子類只關心資料邏輯。
  2. 異常包裝: 統一拋出 Exception 並附帶 rmsName::method::cause,除錯極易定位。
  3. 資源安全: close() 防禦性檢查 null,避免重複關閉崩潰。

Score:高分系統具體實現

資料模型

  • 固定保存前 3 名:String[3] names、int[3] values
  • 預設資料:Magic.D(100)、Tangel(50)、Nick(10)

核心方法

public class Score extends BaseRMS {
    // 載入:遍歷 3 筆記錄,DataInputStream 讀 int + UTF
    protected void loadData() throws Exception {
        for (int i=0; i= values[i]) {
                open();
                for (int j=names.length-1; j>i; j--) {
                    values[j] = values[j-1];
                    names[j] = names[j-1];
                }
                values[i] = score; names[i] = name;
                updateData(); close(); break;
            }
        }
    }
    public boolean isHighScore(int score) throws Exception {
        for (int v : values) if (score >= v) return true;
        return false;
    }
    public void reset() throws Exception { open(); initValues(); updateData(); close(); }
}

序列化細節陷阱與對策

陷阱對策
readUTF() 要求修改版 UTF-8,寫入必須用 writeUTF()嚴格配對 DataOutputStream.writeUTF / DataInputStream.readUTF
記錄長度不固定(字串長度可變)ByteArrayOutputStream 動態擴容,toByteArray() 取實際長度
記錄 ID 從 1 非 0 開始迴圈 i+1 存取
並發存取可能損壞資料單執行緒遊戲通常無慮;若多 MIDlet 共享,需外部 synchronized

進階:遊戲設定同樣適用

作者提到:「遊戲設定本質相同,派生 GameOption extends BaseRMS,啟動時 open() 載入即可」。例如:

class GameOption extends BaseRMS {
    boolean soundOn, vibrationOn; int difficulty;
    protected void loadData() { ... read boolean/int ... }
    protected void createDefaultData() { soundOn=true; vibrationOn=true; difficulty=1; ... }
    protected void updateData() { ... write boolean/int ... }
    // 對外 getter/setter
}

JAD 配置關鍵屬性

MIDlet-Data-Size: 8192  // 最小需求 8KB,安裝時裝置會檢查可用空間
MIDlet-1: RMSAnalyzer,,RMSAnalyzer
MicroEdition-Profile: MIDP-1.0

注意: 實際可用空間常大於宣告值,但宣告過大會導致安裝失敗,建議實測目標機型後留 20% 餘量。

總結:為什麼這套封裝值得參考

  1. 零依賴: 僅用標準 javax.microedition.rms + java.io,無第三方庫。
  2. 擴充性: 新增資料類型只需繼承 BaseRMS 實現三個 abstract 方法。
  3. 健壯性: 統一異常處理、資源釋放、預設值回退。
  4. 效能: 記錄數極少(3 筆),冒泡排序、全量重寫無壓力;大量記錄場景可改用索引檔或分頁載入。

此模式在 Android SharedPreferences、iOS UserDefaults、現代 KV 存儲中依然適用:定義協議、隔離序列化、統一錯誤處理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved