J2ME记录管理存储

779 篇文章 0 订阅
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

  给您的MIDlet应用程序添加数据存储功能

  级别:初级

  SomaGhosh(sghosh@entigo.com)

  应用程序开发者,Entigo

  2002年8月

  移动信息设备框架(MobileInformationDeviceProfile)—移动Java应用程序的平台—为MIDP应用程序提供一种跨多个调用持久存储数据的机制。这种持久存储机制可以被视为一种简单的面向记录的数据库模型,被称为记录管理系统(recordmanageMEntsystem(RMS))。在此,SomaGhosh说明了您的J2ME应用程序怎样能够使用RMS来管理和解释数据。通过一个样本电话数据库,您还将了解到关于这个概念的说明。

  J2ME记录管理系统

  J2ME记录管理系统(RMS)提供了一种机制,通过这种机制,MIDlet能够持久存储数据,并在以后检索数据。在面向记录的方法中,J2MERMS由多个记录存储构成。J2MERMS和MIDlet接口连接的概貌在图1中给出。

  图1.J2MERMS和MIDlet接口连接的概貌

  可以将每个记录存储想像成一个记录集合,它将跨多个MIDlet调用持久存在。设备平台负责在平台正常使用的整个过程(包括重新启动、换电池等)中,尽全力维护MIDlet的记录存储的完整性。

  记录存储在与平台相关的位置(比如非易失性设备存储器)创建,这些位置不直接公开给MIDlet。RMS类调用特定于平台的本机代码,这种本机代码使用标准OS数据管理器函数来执行实际的数据库操作。

  记录存储实现确保所有单个的记录存储操作都是原子的、同步的以及序列化的,因此多个访问将不会出现数据毁坏。记录存储被盖上时间戳来指示它上次被修改的时间。记录存储还维护版本(version),它是一个整数,修改记录存储内容的操作每发生一次,这个数加一。版本和时间戳对于同步目的很有用。

  当MIDlet使用多个线程访问一个记录存储时,协调该访问是MIDlet的责任;如果它不能这样做,可能出现无法意料的结果。同样,如果一个平台使用试图同时访问记录存储的多个线程执行记录存储的同步,那么对MIDlet及其同步引擎之间的记录存储实施排外访问是平台的责任。

  记录存储中的每个记录是一个字节数组,并且有唯一的整数标识符。

  管理设备数据库

  javax.microedition.rms.RecordStore类代表RMS记录存储。它提供了几个方法来管理以及插入、更新和删除记录存储中的记录。

  管理记录存储

  要打开一个记录存储,调用javax.microedition.rms.RecordStore的openRecordStore()方法。publicstaticRecordStoreopenRecordStore(StringrecordStoreNaME,booleancreateIfNecessary)打开具有指定名称recordStoreNaME的记录存储。如果没有具有这个名称的记录存储,那么调用这个方法来创建一个。

  如果记录存储已经打开,这个方法将返回对同一个记录存储对象的引用。

  清单1.打开一个RecordStore

  RecordStorers=RecordStore.openRecordStore("MyAppointMEnts",true);

  一旦所有操作完成,对closeRecordStore()的调用将关闭指定名称的记录存储。当一个记录存储被关闭时,不能进行进一步的操作。

  清单2.关闭一个RecordStore

  Rs.closeRecordStore();

  通过调用deleteRecordStore()方法可以删除指定名称的记录存储。

  清单3.删除一个RecordStore

  RecordStore.deleteRecordStore("MyAppointMEnts");

  插入记录

  MIDlet调用javax.microedition.rms.RecordStore类的addRecord()方法来将一条新记录插入到记录存储中。这是阻塞的原子操作,并返回新记录的recordId。在这个方法返回之前,记录被写到持久存储中。

  publicintaddRecord(byte[]data,intoffset,intnumBytes)插入一条由字节数组data代表的记录,这个数组以offset作为它的起始索引,numBytes作为它的长度。

  清单4.插入一条记录

  Stringappt="newrecord";

  bytebytes[]=appt.getBytes();

  rs.addRecord(bytes,0,bytes.length);

  更新记录

  更新一条特殊记录包括获取这个记录的句柄以及设置新信息。

  publicintgetRecord(intrecordId,byte[]buffer,intoffset)返回存储在由buffer代表的字节数组中给定记录的数据。publicbyte[]getRecord(intrecorded)返回由recordId代表的数据的副本。publicvoidsetRecord(intrecordId,byte[]newData,intoffset,intnumBytes)在recordId所代表记录的位置设置新信息,新信息是以offset作为它的起始索引,并以numBytes作为它的长度的字节流(newData)。

  清单5.更新一条记录

  Stringnewappt="updaterecord";

  Bytedata=newappt.getBytes();

  Rs.setRecord(1,data,0,data.length());

  删除记录

  MIDlet调用deleteRecord()方法来从记录存储中删除记录。

  publicvoiddeleteRecord(intrecordId)删除由recordId代表的记录。这个记录的recordId接下来不能重用。

  清单6.删除一条记录

  Rs.deleteRecord(1);

  数据解释

  J2MEAPI提供某种接口来解释存储在记录存储中的数据。这个过程包括比较记录来确定它们的相对排序。它还包括根据给定条件的内容过滤。

  比较记录

  MIDlet实现RecordComparator接口,并定义compare(byte[]rec1,byte[]rec2)方法来比较两个候选记录。这个方法的返回值必须指示这两条记录的顺序。

  清单7.比较记录并确定相对排序

  Intcompare(byte[]b1,byte[]b2)

  {

  Strings1=newString(b1);

  Strings2=newString(b2);

  If(s1.compareTo(s2)>0)

  ReturnRecordComparator.FOLLOWS;

  Elseif(s1.compareTo(s2)==0)

  ReturnRecordComparator.EQUIVALENT;

  Else

  ReturnRecordComparator.PRECEDES;

  }

  枚举记录

  RecordEnuMEration接口负责枚举记录存储中的记录。它逻辑上维护记录存储中一连串的记录的recordId。枚举器将以记录比较器确定的顺序迭代所有记录(或者如果提供了一个可选的记录过滤器,那么只是一个子集)。如果既没有指定过滤器又没有指定比较器,枚举将以未定义的顺序遍历记录存储中的所有记录。

  清单8.枚举记录

  RecordEnuMErationre=rs.enuMErateRecords(null,null,false);

  If(re.hasNextEleMEnt())

  BytenextRec[]=re.nextRecord();

  过滤记录

  MIDlet实现RecordFilter接口,定义检查记录是否满足应用程序定义的标准的过滤器。这个应用程序实现RecordFilter的match()方法来选择RecordEnuMEration返回的记录。

  清单9.过滤记录

  Publicbooleanmatches(byte[]candidate)

  {

  Strings1=newString(candidate);

  If(s1.equals("XX"))

  Returnstrue;

  Else

  Returnsfalse;

  }

  开发电话约会簿

  在这部分,我们将通过构建一个电话约会簿来说明J2MERMS的功能。这个应用程序将允许用户设置某个日期和时间的约会,取消约会或查看已经设置好的约会列表。一个快捷屏幕视图如图2所示。

  图2.工作中的电话约会簿

  构成这个应用程序的各种屏幕以及屏幕元素的用户界面元素的完整列表在与J2MEWirelessToolkit一起提供的MID框架API文档中可以得到;要获取关于这些元素的更多详细信息,请查阅我早些时候给developerWorks写的一篇文章(请参阅下面的参考资料部分以获取这两个链接)。

  记录存储可以以字节流形式存储记录。在我们的应用程序中,用户输入的日期和时间被连接成一个字符串,转换成字节,然后被存储。

  清单10.将一个新的约会添加到数据库中

  Publicbooleanmatches(byte[]candidate)

  Stringappt=apptNaME+""+apptTiME;

  bytebytes[]=appt.getBytes();

  rs.addRecord(bytes,0,bytes.length);

  同样,这个应用程序以字节流形式检索记录,然后将它转换成一个字符串。这个字符串以####AAAA格式,其中#表示代表时间信息的数字,AAAA表示代表约会描述的字符。这个应用程序解析这个字符串来获得日期和时间信息,并以用户所希望的格式显示它们,比如description-mm/dd/yyyyhh:mmAM_PM。

  清单11.从记录存储检索一条记录

  byteb[]=rs.getRecord(j);

  Stringstr=newString(b,0,b.length);

  清单12.解析从记录存储获得的数据,然后以用户所希望的格式显示

  if(Character.isDigit(str.charAt(i)))

  at+=str.charAt(i);

  else

  naME+=str.charAt(i);

  tiME=Long.parseLong(at);

  java.util.Datedate=newjava.util.Date(tiME);

  java.util.CalendarrightNow=java.util.Calendar.getInstance();

  rightNow.setTiME(date);

  Stringyear=String.valueOf

  (rightNow.get(java.util.Calendar.YEAR));

  Stringmonth=String.valueOf

  (rightNow.get(java.util.Calendar.MONTH)+1);

  Stringday=String.valueOf

  (rightNow.get(java.util.Calendar.DATE));

  StringdisplayNaME=naME

  +"-"+year+""+day;

  用户被允许从记录存储中选择某种约会以及将它们从记录存储中删除。因为为了维持记录中原始的顺序所删除的recordId不能重用,所以这个记录通过特有的字符串模式标记为无效。

  清单13.将一条记录标记为已删除

  Stringdeactive="@";

  byteb[]=deactive.getBytes();

  rs.setRecord(m+1,b,0,b.length);

  当这个应用程序显示一个约会列表时,它检测那些无效记录的字符串模式,然后跳过它们。

  清单14.跳过无效记录

  if(!(str.startsWith("@")))

  {

  //Recordisvalid

  }

  else

  {

  //Recordisinvalid.

  }

  这个应用程序的一个重要的方面是用户界面。各种屏幕有下面这些:

  欢迎表单:欢迎表单显示一个已经设置好的约会列表,如果没有设置约会,则通知用户。它提供继续或退出这个应用程序的各种选项。

  菜单表单:菜单表单给用户提供查看约会、设置新约会或取消约会等选项。

  显示表单:显示表单显示已经设置好的约会列表。

  设置表单:设置表单提供一个日期选择域和一个输入文本域,以提供新约会的详细信息。当用户选择保存时,这条信息被存储到数据库中。

  删除表单:删除表单列出一组约会,并提供选择一个或多个的选项。如果用户选择删除,所选择的这组约会在记录存储中被标记为无效。

  应用程序实现使自己能够响应各种事件的CommandListener和ItemStateListener接口。ItemStateListener使应用程序能够接收指示下面这些东西的内部状态的改变的事件:

  DateField,一个显示日期和时间的可编辑组件

  TextField,一个可编辑文本组件

  ChoiceGroup,一组可选择的元素

  清单15.从屏幕获取值

  //Thedatevalueissettoavariablewhenthe

  //DateFielditemischanged

  if(item==apptDate)

  {

  date=apptDate.getDate();

  apptTiME=String.valueOf(date.getTiME());

  }

  //ThenaMEofappointMEntissettoavariable

  //whenthenaMEinputfieldischanged

  if(item==apptField)

  {

  apptNaME=apptField.getString();

  }

  //IftheChoiceGroupitemstateonDeleteformis

  //changed,itsetsanarrayofappointMEntsselectedfordeletion

  if(item==cg)

  {

  cg.getSelectedFlags(deleted);

  }

  清单16包含这个样本应用程序的完整清单。请参阅参考资料部分中我以前的一篇关于J2ME的文章,以获取关于下载将使您能够在桌面上运行这个程序的设备仿真器的指导。

  总结

  在本文中,我们讲述了MID应用程序持久存储和检索数据的能力;这种机制根据简单的面向记录的数据库建模。J2MEAPIjavax.microedition.rms包提供了一个开发者的方法和接口宝库,从而可以利用MID应用程序的这种独特功能。现在,您应该能够将数据存储集成到您自己的微型Java应用程序中了。

  参考资料

  请通过单击本文顶部或底部的讨论参加关于这篇文章的讨论论坛。

  请下载J2METoolkit来运行和测试您的J2ME应用程序。您还可以浏览这个工具箱中的MID框架API文档,以获取关于J2ME记录存储的信息。

  请通过developerWorksWireless专区关注无线领域。

  developerWorksJava技术专区使您跟上Java领域发生的最新事件。

  请在IBM的普及计算站点查看最新的开发情况。

  用IBM的VisualAgeforJava构建Java应用程序。

  关于作者

  SomaGhosh是计算机科学与工程专业的研究生,在过去七年时间里,她已经开发了涉及广阔范围的电子交易和联网领域的Java应用程序。她认为无线交易代表了业界不远的将来,最近,无线交易被制订为现有桌面组件和模型的无线倡议。Soma目前是Entigo的一名应用程序开发者,Entigo是现实的电子商务解决方案和B2B销售与服务端电子交易产品方面的倡导者和业界领袖。请通过sghosh@entigo.com与她联系。

<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值