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

J2ME 通用日誌框架:從模擬器到真機的調試橋樑

     編輯:J2ME

為什麼需要專屬日誌框架?

J2ME 開發最令人抓狂的莫過於「真機無控制台」。模擬器上 System.out.println 好用得很,一上實體手機——沒輸出、無法追蹤、只能靠 Alert 彈窗硬測,多條訊息還會互相覆蓋。參考 LWUIT 設計理念,本框架提供統一入口、多級別、可擴充、可持久化的日誌方案,讓除錯資訊「有地方存、有辦法看、能隨時清」。

架構三層:介面、實作、管理器

1. Logger 介面——記錄器契約

public interface Logger {
    int FINE = 0, INFO = 10, DEBUG = 20, WARNING = 30, ERROR = 40;
    void log(int level, String info);
    String getLogContent();
    void clearLog();
}

五級別對應 Java SE java.util.logging.Level,便於移植既有代碼。

2. LogShower 介面——顯示器契約

public interface LogShower {
    void showLog(String logContent, BackAction action);
    interface BackAction { void back(); }
}

解耦「怎麼記」與「怎麼看」:同一份日誌可用 List、TextArea、Canvas 甚至 HTTP 上傳伺服器呈現。

3. LogManager 管理器——單一入口

public final class LogManager {
    private static Logger log = new LoggerImpl();
    private static LogShower shower = new LogShowerImpl();

    public static void install(Logger log) { LogManager.log = log; }
    public static void install(LogShower shower) { LogManager.shower = shower; }

    public static void info(String msg)  { log.log(Logger.INFO, msg); }
    public static void debug(String msg) { log.log(Logger.DEBUG, msg); }
    public static void error(String msg) { log.log(Logger.ERROR, msg); }
    public static void warning(String msg){ log.log(Logger.WARNING, msg); }
    public static void fine(String msg)  { log.log(Logger.FINE, msg); }

    public static void showLog(BackAction back) { shower.showLog(log.getLogContent(), back); }
    public static void clearLog() { log.clearLog(); }
    // ... 內建預設實作 LoggerImpl / LogShowerImpl
}

預設實作亮點

LoggerImpl:記憶體緩衝 + 執行緒/時間標記

static class LoggerImpl implements Logger {
    private StringBuffer sb = new StringBuffer(1024);
    public void log(int level, String info) {
        sb.append('[').append(Thread.currentThread()).append('-')
          .append(Util.getCurrentTime()).append("] ")
          .append(getLevelName(level)).append(':').append(info).append('\n');
    }
    private String getLevelName(int level) {
        switch(level) {
            case FINE: return "FINE";
            case INFO: return "INFO";
            case DEBUG: return "DEBUG";
            case WARNING: return "WARNING";
            case ERROR: return "ERROR";
            default: return "UNKNOWN";
        }
    }
    public String getLogContent() { return sb.toString(); }
    public void clearLog() { sb.delete(0, sb.length()); }
}

LogShowerImpl:基於 LWUIT 的互動式檢視器

static class LogShowerImpl implements LogShower {
    public void showLog(String logContent, final BackAction action) {
        Form form = new Form("日誌內容");
        form.setScrollable(false);
        final TextArea ta = new TextArea(logContent, 5, 10);
        ta.setEditable(false);
        form.addCommand(new Command("返回") {
            public void actionPerformed(ActionEvent ae) { action.back(); }
        });
        form.addCommand(new Command("清除") {
            public void actionPerformed(ActionEvent ae) {
                LogManager.clearLog(); ta.setText("");
            }
        });
        form.setLayout(new BorderLayout());
        form.addComponent(BorderLayout.CENTER, ta);
        form.show();
    }
}

進階用法:RMS 持久化日誌

預設實作僅駐留記憶體,長時間運行易 OOM。自訂 RMSLogger 三步走:

  1. log() 將字串 getBytes() 後 RecordStore.addRecord()
  2. getLogContent() 遍歷 RecordEnumeration 還原完整字串
  3. clearLog() 呼叫 RecordStore.deleteRecordStore() 徹底清空

再 LogManager.install(new RMSLogger()) 即可無縫切換。

實戰經驗總結

  • 等級過濾:發布版僅開啟 WARNING 以上,開發版全開,避免 I/O 爆量。
  • 異步寫入:高頻日誌(如遊戲幀率)建議佇列 + 獨立執行緒批次落盤。
  • 體積控制:RMS 記錄數超過閾值(如 200 條)自動循環覆寫最舊記錄。
  • 遠端收集:LogShower 實作可改為 HTTP POST 上傳錯誤日誌至伺服器,實現「雲端除錯」。

結語

這套框架僅 3 個類、< 2 KB,卻解決了 J2ME 開發 90% 的調試痛點。核心思想——介面隔離變化點、管理器統一入口、預設實作開箱即用——同樣適用於 Android、嵌入式 Linux 等資源受限環境。下次真機跑不動時,別再硬塞 Alert 了,裝上它,睡個好覺。

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