当前位置: 首页 > news >正文

J2ME最佳实践之RMS操作

作者:asklxf 文章来源:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=966

编写灵活的RMS应用

MIDP应用程序的标准持久化方案就是使用RMS。RMS类似于一个小型数据库,RecordStore相当于数据库的表,每个“表”由若干记录(Record)构成,一条记录就是一个用int表示的记录号RecordID和用byte[]表示的内容。记录号可以看作是“主键”,byte[]数组存储内容。

RMS提供的记录操作可以实现根据ID直接获得记录,或者枚举出一个表中的所有记录。

枚举记录是非常低效的,因为只能比较byte[]数据来确定该记录是否是所需的记录。通过ID获得记录是高效而方便的,类似于SQL语句“SELECT byteArrayData FROM recordStoreName WHERE RecordID=?”。然而,通常应用程序很难知道某条记录的ID号,而RMS记录的“主键”又仅限于int类型,无法使用其他类型如String作为“主键”来查找。因此,对于需要存取不同类型对象的应用程序而言,就需要一个灵活的RMS操作框架。

我们的基本设想是,如果能使用String作为“主键”来查找记录,就能非常方便地获得所需的内容。例如,应用程序设置可以通过"sys.settings"获得byte[]数组,并依次读取出设置,用户登录信息可以通过"user.info"获得byte[]数组,再分解出用户名和口令。

因此,我们实现一个StorageHandler类,提供唯一的RMS访问接口,使得其他类完全不必考虑底层的RMS操作,只需提供能标识自身的一个String即可。

如果我们能实现一种类似于数据库索引的查找表,就能根据String关键字查找某条记录。因此,我们使用一个名为"index"的RecordStore来存储所有的索引,每一条索引都指向某一条具体记录的ID,设计一个IndexEntry表示一条索引:

class IndexEntry {
private int selfId; // IndexEntry的ID
private int recordId; // 对应记录的ID
private String key; // 访问记录的Key
}

根据索引查找,分3步进行:

1.在名为"index"的RecordStore中根据String查找对应的IndexEntry。
2.取出IndexEntry,获得记录ID号。
3.根据ID号获得另一个RecordStore的记录,然后就可以读取、更新和删除该记录。

如下图所示:

由于IndexEntry保存的数据很少,为了加快查找速度,可以在应用程序启动时,把所有的IndexEntry读入一个Vector,在后面的操作中更新这个Vector并与RecordStore保持同步。

为了处理不同类型的数据,所有可通过StorageHandler存取的类都必须实现一个Storable接口:

public interface Storable {
String getKey();
void getData(DataOutputStream output) throws IOException;
void setData(DataInputStream input) throws IOException;
}

前面已经提到,在MIDP应用程序中,序列化一个类的最佳方法是使用DataInputStream和DataOutputStream。因此,需要持久化的类可以通过getData()和setData()方法非常方便地存取。假定应用程序的类UserInfo保存了用户的登录名、口令和是否自动登录的信息:

public class UserInfo {
String username;
String password;
boolean autoLogin;
}

为了能将UserInfo存入RMS,需要实现Storable接口:

class UserInfo implements Storable {
String username;
String password;
boolean autoLogin;
public String getKey() { return "user.info"; } // 提供一个唯一标识符即可
public void getData(DataOutputStream output) throws IOException {
output.writeUTF(username);
output.writeUTF(password);
output.writeBoolean(autoLogin);
}
public void setData(DataInputStream input) throws IOException {
username = input.readUTF();
password = input.readUTF();
autoLogin = input.readBoolean();
}
// getters here...
}

要保存UserInfo,只需调用StorageHandler的保存方法:

StorageHandler.storeOrUpdate(userinfo);

要读取UserInfo,调用StorageHandler的读取方法:

UserInfo userinfo = new UserInfo();
StorageHandler.load(userinfo);

这样,需要读取或保存数据的类完全不必涉及底层的RMS操作,大大简化了应用程序的设计,增强了源代码的可复用性与可维护性。

相关文章:

  • 在MIDP2.0中操作图片像素
  • 配置 vue 环境
  • 介绍J2ME的几个重要概念
  • 谷歌浏览器插件
  • 基于MIDP实现ResourceBundle类
  • Node.js 基础-01
  • vscode保存代码,自动按照eslint规范格式化代码设置(vscode最新版配置)
  • 关注J2ME WTK2.2新特性
  • 高级前端面试题
  • 介绍MIDP的属性问题
  • 破解 vue3.x 新特性
  • UniJa2.1声音播放问题(MIDI格式)
  • 在MIDP2.0中调用平台服务
  • 前端模块化
  • 搭建OTA下载服务器
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • Koa2 之文件上传下载
  • node和express搭建代理服务器(源码)
  • PHP那些事儿
  • springMvc学习笔记(2)
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • 从0到1:PostCSS 插件开发最佳实践
  • 前端相关框架总和
  • 数据可视化之 Sankey 桑基图的实现
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • Linux权限管理(week1_day5)--技术流ken
  • mysql面试题分组并合并列
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • ​MySQL主从复制一致性检测
  • # Apache SeaTunnel 究竟是什么?
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • ###项目技术发展史
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (SpringBoot)第二章:Spring创建和使用
  • (八)Spring源码解析:Spring MVC
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .Net多线程总结
  • .NET面试题(二)
  • .Net小白的大学四年,内含面经
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • [.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序...
  • [Android 数据通信] android cmwap接入点
  • [AutoSar]BSW_Memory_Stack_004 创建一个简单NV block并调试
  • [BUUCTF 2018]Online Tool
  • [c语言]小课堂 day2
  • [Delphi]一个功能完备的国密SM4类(TSM4)[20230329更新]
  • [Head First设计模式]策略模式
  • [IOI2007 D1T1]Miners 矿工配餐
  • [MRCTF2020]Ez_bypass1