■ 引言
在上讲中,我们认识到汲取音乐播放的专长,能够制作成拥有bgm和音效、表现力丰富的应用程序。在本讲中,我们主要就应用程序本身内部保持的数据保存、读取进行详细阐述。
■ 数据的保存读取
rms:
要在应用程序中保存用户设定和高分等相关信息,所以必须在手机终端上的记忆中保存数据。midp上定义了称之为rms(record management system)的数据库系统。rms中有称为“record store”的列表,其中存在名为record 的entry。record按照字节排列,用id可以识别。利用下面的类、接口可以操作record store和record。
| 类、接口名 | 作用 |
| recordstore | 表示record store的类 |
| recordenumeration | 列举record的接口 |
| recordcomparator | 定义record comparator的接口 |
| recordfilter | 定义record过滤的接口 |
| recordlistener | 监视record store变更的接口 |
表 1
recordstore
表示record store的是record store类。record store是用recordstore 中的static方法的open record store制作的。
recordstore.openrecordstore("recordstorename", true);
第2个自变量转化成“true”后,名为“record store name”的record store存在的情况下,能够打开保存的record store。但是,名为“record store name”的record store不存在的情况下,则会制作新的record store,并打开所制作的record store 。
第2个自变量转化成“false”后,名为“record store name”的record store存在的情况下,能够打开保存的record store。但,不存在的情况下,则放弃record store not found exception。
操作record store时,应该在操作前打开record store,并在操作完后关闭record store。利用刚刚介绍的record store的static方法――open record store打开record store。利用record store的引证方法的close record store按照下面的叙述可以关闭record store。在这儿将关闭的record store 例子表示为rs。
rs.closerecordstore();
以下是表示针对 record store 的连贯操作。(ex. 1)
| recordstore rs = null; try{ // 打开record store rs = recordstore.openrecordstore("recordstorename",true); 记述针对record store的操作 ? ? }catch(exception e){ }finally{ if(rs != null){ try{ // 关闭record store rs.closerecordstore(); }catch(exception e){ } } } |
ex. 1
按照下面所述的record store的static方法清除record store。
recordstore.deleterecordstore("recordstorename");
rms的限制
rms是非常单纯的数据库系统,所以只需准备最小限度的操作。因此,一般数据库系统所具有的处理控制和系统故障的恢复功能,在rms上是不能被支持的。
record操作
增加record
利用以下record store类的方法增加record 。
int addrecord(byte[] data,int offset, int numbytes)
在data中指定希望保存的数据字节排列、在offset中指定数据显示排列中的数据开始位置、在numbytes中指定保存数据的字节数。能在numbytes中指定0。此时,null被收藏在record中。另外,增加数据的record的id作为返还值返还。
清除record
利用以下方法清除record 。
void deleterecord(int recordid)
指定用recordid清除record中的id。对应的record不存在的情况下,放弃例外。而且,清除后的recordrecordid也不能再次利用。
更改record
利用以下方法更改record 。
void setrecord(int recordid, byte[] newdata, int offset, int numbytes)
指定recordid中更改的record,并在newdata中指定新收藏的数据字节排列。对应的record不存在的情况下,放弃例外。
获取record
利用下面的方法获取record。
int getrecord(int recordid, byte[] buffer, int offset)
byte[] getrecord(int recordid)
上述方法是指,从offset的位置上复制recordid方法指定的record内容到buffer字节排列。返还值是所复制的数据的字节数。
下面的方法是指,recordid所指定的record内容作为返还值返还。
record store的信息
利用如下方法可以获得record store操作和record 操作之外的record store信息。
| 方法 | 功能 |
| public int getlastmodified() | 用long获取最后的修改时刻。用system.currenttimemillis()形成能够取得的形式相同的形式。 |
| public int getnextrecordid() | 获取下一个recordid |
| public int getnumrecords() | 获取record store中的record 数。 |
| public int getversion() | 获取record store的版本编号。版本编号通常在每次修改完record store后都会自动加1。 |
| public int getsizeavailable() | 获取record store的容许量。 |
| public int getsize() | 获取record store的占有字节数。 |
| public static string[] listrecordstores() | 全部获取record store名。 |
表 2
recordenumeration
rms中准备了能够访问record store中的全部record 的recordenumeration接口。由于厂商进行具体实际安装,所以开发者就没必要实际安装recordenumeration了。recordenumeration是具有双向链接的list,在各自的note中都保存了recordid。
制作recordenumeration
利用下面的record store instance方法制作recordenumeration。
recordenumeration enumeraterecords(recordfilter filter, recordcomparator comparator, boolean keepupdated)
一旦keepupdated成为true,就会增加record store中的record 的更改量,同时recordenumeration也会随着更新。成为false时,只要不呼出recordenumeration接口的rebuild()方法,即使在record store上增加变更,也不能反映,但可能会得到清除后的recordid。在filter中将用于过滤record的recordfilter接口指定为实际安装的类的接口。此外,在comparator中将用于定义record顺序号的recordcomparator接口指定为实际安装的类的接口。后面将详细说明。
访问record
应用以下方法访问利用recordenumeration的record。
| 方法 | 作用 |
| void destroy() | 取消recordenumeration |
| boolean hasnextelement() | 调查是否有下一个record |
| boolean haspreviouselement() | 调查是否有前一个record |
| byte[] nextrecord() | 取得下一个record |
| int nextrecordid() | 取得下一个record的id |
| byte[] previousrecord() | 取得前一个record |
| int previousrecordid() | 取得前一个record的id |
| int numrecords() | 取得record的数 |
| void rebuild() | 再构筑recordenumeration |
| void reset() | 将record的pointer返回到开头 |
表 3
如下所示的是利用recordenumeration所取得的简单record。
| import javax.microedition.midlet.*; import javax.microedition.rms.*; /** /** recordstore rs = null; } protected void pauseapp() { } } |
ex. 2
recordfilter
用recordenumeration取得record时,指定条件能够过滤record。实际安装recordfilter接口,该instance在recordenumeration完成时就成为构造函数的自变量,所以能够过滤。recordfilter接口中定义了如下方法。
boolean matches(byte[] candidate)
此方法中记述了过滤的条件,还记述了若条件适合则返回到true,若不合适则会返回到false。
以下显示的是实际安装完recordfilter的testfilter。此例中过滤了比用构造函数所指定的数值还低的数值。
import javax.microedition.rms.recordfilter; /** |
ex. 3
在取得ex. 2的程序的recordenumeration画面中,将程序更改为
re = rs.enumeraterecords(new testfilter(4),null,true);
在自变量上指定ex. 3的testfilter时的运行结果如下所示。(图 1)。
recordcomparator
用recordenumerator取得record时,能够进行利用recordcomparator接口所取得的record的comparator。recordcomparator中定义了下面方法。
int compare(byte[] rec1, byte[] rec2)
返还值中返还了以下3个定数。
| recordcomparator.precedes | 在comparator上record rec1到达record rec2的前一位置时 |
| recordcomparator.follows | 在comparator上record rec1到达record rec2的后一位置时 |
| recordcomparator.equivalent | 在comparator上record rec1到达record rec2的同一位置时 |
表 4
以下显示的是实际安装recordcomparator的testcomparator。在此例中,按照数值的大小顺序进行比测record。(ex. 4)
| import javax.microedition.rms.recordcomparator; /** /** |
ex. 4
取得ex. 2程序的recordenumeration的画面中,程序变更为
re = rs.enumeraterecords(new testfilter(3),new testcomparator,true);
并自变量中指定ex. 4的testcomparator时的运行结果。该内容如下图所示(图 2)。
图 2
recordlistener
利用recordlistener接口,能够监视针对record store的变更。例如,同期取得两个record store的情况下,单方面的record store被更改时,能够实现在单方的record store上增加更改等的操作。
recordlistener中有recordchanged,recordadded,recorddeleted等3个种类的事件,并分别定义了每个方法。
void recordadded(recordstore recordstore, int recordid)
void recordchanged(recordstore recordstore, int recordid)
void recorddeleted(recordstore recordstore, int recordid)
利用record store类中所准备的如下方法能够在record store 上登记recordlistener。
void addrecordlistener(recordlistener listener)
void removerecordlistener(recordlistener listener)
以下是实际安装recordlistener的instance。此示范程序中,可以监视并复制record的操作。
import javax.microedition.midlet.*; /** /** recordstore rs = null; protected void pauseapp() { } /** /** /** } |
ex. 5
下图是运行结果。(图3)该图能够确认record 操作内容是被监视并被表示的。
图3
开始制作应用程序了。
手机记事本的说明
利用midp的rms功能,制作手机简易记事本应用程序。
就是用户输入记事内容,保存输入的内容、并进行记事的编辑、清除等所谓的简单的记事本应用程序。
如下是画面结构。
| memo list画面 | 显示memo list。可以进行memo的重新制作和显示。显示每个memo的最后访问日期和时间。 |
| memo画面 | 表示memo的内容。可以进行memo的编辑、清除。 |
下图是画面迁移图。(图 4)
图 4
手机记事本的实际安装
下面是实际安装的顺序
1. 制作模型
2. 制作画面的实物模型
3. 制作rms的操作
1. 制作模型
在本记事本中,要制作成表示一个一个的记事的memo类。memo类中有最后访问日期和时间、记事内容等属性。(ex. 6)
| import java.io.*; import java.util.*;
/** /** /** |
ex. 6
2. 制作画面的实物模型
接下来制作画面与画面之间的迁移。
本讲讲述利用高级api制作画面。memo list用高级api的list表示,memo画面则利用textbox。
而且,还要在各个画面中设定命令。分别设定如下表格所示的命令。
| memo list画面 | add | 重新制作memo |
| show | 显示memo | |
| memo画面 | ok | 刷新memo的内容 |
| delete | 清除memo |
以下内容是实际安装画面实物模型的具体步骤。对于实物模型,sample source命令实际安装所记述的处理后,则应用程序就完成了。
| import java.util.vector; import javax.microedition.lcdui.*; /** // 画面类 // 作成记事显示画面 } /** /** // 从record store读取信息 // 转换到memo list画面 /** /** /** if (d == list) { } else if (c == delete) { // 转换到memo list |
按照上面表格中的程序所示,则可完成实物模型,并能完成应用程序的大致框架。
3. 完成rms的操作
马上就要完成rms操作了。
现在我们只想在 record store中原样保存memo内容,所以就要在刚才作成的memo类中进行精雕细琢。从取得memo类字节排列方法和字节排列中增加制作memo类的构造函数。而且,还能用memo类保存record id。(record store中保存的record id则不写入。)
利用bytearrayoutputstream类和dataoutputstream类,变换字节排列中的类的内容。memo类中记述了如下instance方法。(ex. 7)
| /** * 变换字节排列 */ public byte[] tobytes(){ byte[] data = null; try{ bytearrayoutputstream baos = new bytearrayoutputstream(); dataoutputstream out = new dataoutputstream(baos); out.writelong(date.gettime()); out.writeutf(content); data = baos.tobytearray(); baos.close(); out.close(); }catch(exception e){ } return data; } |
ex. 7
还是从字节排列中制作作成memo对象的构造函数吧!利用bytearrayinputstream类、datainputstream类,如下记述。(ex. 8)
| public memo(byte[] data){ bytearrayinputstream bais = new bytearrayinputstream(data); datainputstream in = new datainputstream(bais); try{ date = new date(in.readlong()); content = in.readutf(); }catch(exception e){ } } |
ex. 8
为能保持memo类中的record id ,增加一个属性。由此,则完成了memo类。以下程序显示的是完成后的memo类 。(ex. 9)
| import java.io.*; import java.util.*;
/** /** /** } |
ex. 9
接下来,开始在mobilememo类上制作rms操作吧。rms操作有如下四种方法。
- 全部取得memo内容
- 重新制作memo内容
- 保存memo内容
- 清除memo内容
全部取得memo内容的方法中,利用recordenumeration全部取得record,并从取得的record字节排列中制作memo对象。制作完成的memo对象能够将vector型的memos作为instance变量加以定义,并在此保持。而且,从record store中全部取得完record 后,则可以按照record 更新record store画面。在此,定义了如下方法。(ex. 10)
| /** // 从record store更新信息 */ public void reloadfromrsm() { memos.removeallelements(); // 取得record recordstore rs = null; recordenumeration re = null; try { rs = recordstore.openrecordstore(rs_name, true); re = rs.enumeraterecords(null, null, true); // 取得record while (re.hasnextelement()) { int id = re.nextrecordid();// 取得record id byte[] data = rs.getrecord(id);// 取得record memo memo = new memo(data);// 完成memo memo.setrecid(id);// 设定record id memos.addelement(memo);// 增加memo } } catch (exception e) { } finally { // 取消recordenumeration if (re != null) { try { re.destroy(); } catch (exception e) { } } // 关闭record store if (rs != null) { try { rs.closerecordstore(); } catch (exception e) { } } } // 更新memo list } |
ex. 10
转换到memo list画面时呼出ex. 10的方法。
接着,继续记述余下的操作。这些操作主要针对record store进行更改。即使将每一步操作步骤都详细记述也是没关系的,为了简单化,现在将针对record store的操作都整合在一个方法中,并记述根据if文的区分处理。(ex. 11)
| /** * 重新制作memo */ public memo createnewmemo() { memo memo = new memo(); return changememotorms(memo, add); } /** /** /** // memo的更改被反映到record store |
ex. 11
下面将完成的处理与命令处理结合在一起。(ex. 12)memo显示画面中显示的memo内容被保持为名为currentmemo的instance变量,并且在memo显示画面中,可以显示currentmemo内容。
| /** * 命令处理 */ public void commandaction(command c, displayable d) { if (d == list) { // 转入memo list |
ex. 12
■ 完成
本讲中所制作的源码如下所示:
- mobilememo.java
- memo.java
运行后如下:
| |
■ 总结
在本讲中,介绍了利用rms可以进行数据保存和读取。由于利用这种功能,能够在应用程序内永久保存数据,所以能够制作成高级功能的应用程序。从下讲开始,计划介绍手机网络的有关知识。学习了第一讲[创建开发环境] 到第七讲的[网络],有关手机java的相关技术应该有个大概的轮廓了。以这些基础的java技术信息为基础,一定可以制作成出色的应用程序的!
闽公网安备 35060202000074号