RecordFilter的定義非常的簡單,他只定義了一個方法那就是boolean matches(byte[] data)。
public interface RecordFilter {
boolean matches( byte[] recordData );
}
使用起來也非常簡單,我們只需要實現這個方法並根據需要返回boolean類型的值就可以了,通常我們在查找紀錄的時候使用這個接口,把它作為一個參數傳遞給enumerateRecords()方法,例如
RecordEnumeration records = rs.enumerateRecords(new RecordEntryFilter(key),null,false),首先我們看看這個方法的參數,第一個參數是RecordFilter,它就是用來篩選數據庫中的紀錄的,篩選的條件就是我們上面定義的方法,boolean matches(byte[] data),第二個參數是RecordComparator,它是對選擇出來的數據進行排序的,如果你不指定的話就按照默認的順序排序。第三個參數是boolean類型的,如果是true的話,那麼record會跟蹤rms中的數據變化,這是比較昂貴的開銷,我一般都是用false的。得到records後我們可以進行很多有用的操作,具體的方法有:
public interface RecordEnumeration {
void destroy();
boolean hasNextElement();
boolean hASPreviousElement();
boolean isKeptUpdated();
void keepUpdated( boolean keepUpdated );
byte[] nextRecord() throws InvalidRecordIDException,
RecordStoreNotOpenException,
RecordStoreException;
int nextRecordId() throws InvalidRecordIDException;
int numRecords();
byte[] previousRecord() throws InvalidRecordIDException,
RecordStoreNotOpenException,
RecordStoreException;
int previousRecordId() throws InvalidRecordIDException;
void rebuild();
void reset();
}
其中標記的方法很常用應該記住。我們實現RecordFilter的時候通常是會寫成一個類的內部類,這非常普遍也很合理。我下面的程序依然使用這樣的方法,
private static class RecordEntryFilter implements RecordFilter
{
private String key;
public RecordEntryFilter(String key) {
this.key = key;
}
public boolean matches(byte[] data)
{
try
{
return RecordEntry.matches(data, key);
} catch (IOException e)
{
e.printStackTrace();
return false;
}
}
}
在例子用我們向RMS中存入幾個數據實體,它包括一個username和一個phonenumber字段。我們寫入和讀出字段的時候可以使用系列之二中的序列化機制。
import Java.io.*;
public class RecordEntry
{
private String userName;
private String phoneNum;
public RecordEntry() {
}
public RecordEntry(String userName, String phoneNum) {
this.userName = userName;
this.phoneNum = phoneNum;
}
public String getPhoneNum()
{
return phoneNum;
}
public void setPhoneNum(String phoneNum)
{
this.phoneNum = phoneNum;
}
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
public byte[] serialize() throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream DOS = new DataOutputStream(baos);
DOS.writeUTF(userName);
DOS.writeUTF(phoneNum);
return baos.toByteArray();
}
public static RecordEntry deserialize(byte[] data) throws IOException
{
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
RecordEntry record = new RecordEntry();
record.userName = dis.readUTF();
record.phoneNum = dis.readUTF();
return record;
}
public static boolean matches(byte[] data,String key) throws IOException
{
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
return dis.readUTF().equals(key);
}
public String toString()
{
return userName+":"+phoneNum;
}
}
我們本文要講述的另一個重點是如何使用RecordEnumeration,相關的代碼寫在了一個RecordModel類裡面如下:
import Java.io.IOException;
import Javax.microedition.rms.*;
public class RecordModel
{
private RecordStore rs;
private boolean firstTime = true;
public static final String NAME = "record";
private RecordEntry[] record = { new RecordEntry("ming", "12345"),
new RecordEntry("pain", "123456"),
new RecordEntry("Linux", "234566"),
new RecordEntry("mingtian", "3456677") };
private static class RecordEntryFilter implements RecordFilter
{
private String key;
public RecordEntryFilter(String key) {
this.key = key;
}
public boolean matches(byte[] data)
{
try
{
return RecordEntry.matches(data, key);
} catch (IOException e)
{
e.printStackTrace();
return false;
}
}
}
public RecordModel() {
try
{
rs = RecordStore.openRecordStore(NAME, true);
} catch (RecordStoreException e)
{
e.printStackTrace();
}
if(firstTime)
{
init();
firstTime = false;
}
}
public void init()
{
try
{
for (int i = 0; i < record.length; i++)
{
byte[] data = record[i].serialize();
rs.addRecord(data, 0, data.length);
}
} catch (IOException e)
{
e.printStackTrace();
} catch (RecordStoreException e)
{
e.printStackTrace();
}
}
public RecordEntry[] getRecord(String key)
{
try
{
if (rs.getNumRecords() > 0)
{
RecordEnumeration records = rs.enumerateRecords(
new RecordEntryFilter(key), null, false);
int length = records.numRecords();
if (length == 0)
{
return new RecordEntry[0];
} else
{
System.out.println(length);
RecordEntry[] record = new RecordEntry[length];
for (int i = 0; i < length; i++)
{
record[i] = RecordEntry.deserialize(rs
.getRecord(records.nextRecordId()));
}
return record;
}
} else
{
return new RecordEntry[0];
}
} catch (RecordStoreException e)
{
e.printStackTrace();
return new RecordEntry[0];
} catch (IOException e)
{
e.printStackTrace();
return new RecordEntry[0];
}
}
}
其中標記為灰色的代碼是我們應該重點掌握的,下面是RecordFilterMIDlet類的代碼:
import Javax.microedition.lcdui.*;
import Javax.microedition.midlet.MIDlet;
import Javax.microedition.midlet.MIDletStateChangeException;
public class RecordFilterMIDlet extends MIDlet implements ItemStateListener
{
private Display display;
private Form mainForm;
private TextField textFIEld;
private RecordModel model;
protected void startApp() throws MIDletStateChangeException
{
display = Display.getDisplay(this);
mainForm = new Form("Test");
model = new RecordModel();
textField = new TextField("input:", null, 20, TextFIEld.ANY);
mainForm.append(textFIEld);
mainForm.setItemStateListener(this);
display.setCurrent(mainForm);
}
protected void pauseApp()
{
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException
{
}
public void itemStateChanged(Item item)
{
if (item == textFIEld)
{
String input = textFIEld.getString();
RecordEntry[] record = model.getRecord(input);
if (record.length == 0)
{
System.out.println("no record");
} else
{
for (int i = 0; i < record.length; i++)
{
System.out.println(record[i]);
}
}
}
}
}
為了方便我沒有在手機界面上顯示,而是輸出到控制台。下面是在input內輸入ming的時候在控制台打印出來的結果:
no record
no record
no record
1
ming:12345
你可能想把以輸入字段為開頭的記錄篩選出來,就像在通訊錄中查詢一樣。那麼你可以在Filter中添加一個int類型的type來告訴實體中的matches()方法應該如何做。這樣就可以篩選出你所需要的記錄了:)
還是那句話,希望對大家有用!本來還想在系列5中介紹我自己實現的一個個人通信錄,程序已經寫完,大概有3k的代碼吧,基本覆蓋了前面所講述的專題。由於我准備投稿,因此決定不繼續寫Record Management System的內容了。