📄 jun01_ericg.txt
字号:
display.setCurrent( new SampleList( mode ) );
}
}
private void showSelection( boolean implicit ){
Alert alert = new Alert(
implicit ? "Implicit Selection"
: "Explicit Selection" );
StringBuffer buf = new StringBuffer();
if( mode == MULTIPLE ){
boolean[] selected = new boolean[ size() ];
getSelectedFlags( selected );
for( int i = 0; i < selected.length; ++i ){
if( selected[i] ){
if( buf.length() == 0 ){
buf.append( "You selected: " );
} else {
buf.append( ", " );
}
buf.append( getString( i ) );
}
}
if( buf.length() == 0 ){
buf.append( "No items are selected." );
}
} else {
buf.append( "You selected " );
buf.append( getString( getSelectedIndex() ) );
}
alert.setString( buf.toString() );
alert.setTimeout( Alert.FOREVER );
display.setCurrent( alert, display.getCurrent() );
}
}
}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ENUMERATING, FILTERING, AND SORTING MIDP RECORD STORES
The Record Management System (RMS), part of the Mobile
Information Device Profile (MIDP), lets you store arbitrary byte
arrays as records in a database. The set of records is referred
to as a record store. The RMS assigns a record ID to each record
when it is created. The record ID is an integer greater than or
equal to 1. The application uses this ID to get and set the
content of a record.
Record IDs are unique within a record store. In other words,
after a record ID has been assigned to a record, the record ID
is not reused, even if that record is deleted. This makes it easy
to track individual records. It does, however, pose a problem:
how do you get a list of all the records in a record store, given
that they aren't necessarily in a continuous, sequential order?
The answer is to use an enumeration.
The RecordStore class defines an enumerateRecords method that
returns a RecordEnumeration. RecordEnumeration is an interface
whose purpose is similar to the java.util.Enumeration interface,
but with more capabilities. (The RecordEnumeration interface,
like all RMS classes and interfaces, is defined in the
javax.microedition.rms package). Here is the definition for
RecordEnumaration:
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();
}
RecordEnumeration lets you traverse through a set of records.
Unlike Enumeration, however, RecordEnumeration allows for
bidirectional traversal of that set -- you can go backwards
through the set of records as well as forwards. The set of
records to traverse is defined by the enumerateRecords method.
To iterate over the entire set of records in a record store,
do the following:
RecordStore rs = .....; // an open record store
RecordEnumeration enum = null;
try {
enum = rs.enumerateRecords( null, null, false );
while( enum.hasMoreElements() ){
int id = enum.getNextRecordId();
// do something here with the record
}
}
catch( RecordStoreException e ){
}
finally {
enum.destroy();
}
The first two arguments to the enumerateRecords method are
used to filter and sort the records in an enumeration. (This tip
will discuss filtering and sorting shortly.) The last argument
determines whether the enumeration tracks changes to the record
store. If the last argument is true, the enumeration updates
itself as records are added to or deleted from a record store.
This can be an expensive operation, however, and for most
applications tracking is not required. Note that enumerateRecords
throws RecordStoreNotOpenException if the record store is not
open. RecordStoreNotOpenExceptio is a subclass of
RecordStoreException.
RecordEnumeration defines two methods to traverse forward through
the enumeration: getNextRecordId and getNextRecord. It also
defines two methods to traverse backwards: getPreviousRecordId
and getPreviousRecord. Each method moves to the next or previous
record in the enumeration, returning either the ID of the record
(getNextRecordId and getPreviousRecordId) or its contents
(getNextRecord and getPreviousRecord). An application calls
hasNextElement or hasPreviousElement to determine if there
are any more records to traverse in a specific direction.
You can reset the enumeration at any time by calling reset.
When an application is done with an enumeration it must call the
enumeration's destroy method. This frees up any resources used by
the enumeration.
If the first two arguments to enumerateRecords are null, all the
records in the record store are returned in an undefined order. To
return a subset of the records or to return the records in a
specific order, you must define a filter, a comparator, or both.
To do this, pass in objects that implement the RecordFilter or
RecordComparator interfaces, depending on whether you defined
a filter, comparator, or both.
The RecordFilter interface defines a single method:
public interface RecordFilter {
boolean matches( byte[] recordData );
}
A filter is an instance of a class that implements the
RecordFilter interface. If a filter is defined in the call to
enumerateRecords, the filter's matches method is called for each
record in the record store. The matches method determines if the
record is included in the enumeration. Here, for example, is a
filter that filters out empty records or records whose first byte
is set to zero:
public class MyFilter implements RecordFilter {
public boolean matches( byte[] recordData ){
return( recordData.length > 0 && recordData[0] != 0 );
}
}
Use the filter like this:
enum = rs.enumerateRecords( new MyFilter(), null, false );
Note that the filter is passed the contents of a record,
but not the record ID or a reference to the record store itself.
The RecordComparator interface also defines a single method:
public interface RecordComparator {
boolean compare( byte[] rec1, byte[] rec2 );
int EQUIVALENT = 0;
int FOLLOWS = 1;
int PRECEDES = -1;
}
A comparator is an instance of a class that implements the
RecordComparator interface. If a comparator is defined in the
call to enumerateRecords, the enumerator sorts the records in the
set. The enumerator calls the comparator's compare method to
determine the relative order of two records. The comparator
returns EQUIVALENT if both records are equivalent, FOLLOWS if the
first record follows the second record, or PREVIOUS is the first
precedes the second record. Here is a comparator that sorts
records based on their length:
public class MyComparator implements RecordComparator {
public boolean compare( byte[] rec1, byte[] rec2 ){
if( rec1.length == rec2.length ){
return EQUIVALENT;
} else if( rec1.length < rec2.length ){
return PRECEDES;
} else {
return FOLLOWS;
}
}
}
Of course, most comparators would compare records based on their
contents. Use the comparator like this:
enum = rs.enumerateRecords( null, new MyComparator(), false );
Again, only the contents of the records to compare are passed to
the comparator.
Both a filter and a comparator can be associated with an
enumeration. The filter is called first to determine which
records are in the enumeration. The comparator is then called to
sort those records.
If tracking is enabled, filtering and sorting occurs whenever the
record store is modified. This can be quite expensive to perform.
You can enable or disable an enumeration's tracking of the
underlying record store by using the keepUpdated method.
If tracking is disabled but you want to "refresh" the enumeration
from the current set of records in the record store, call
the rebuild method.
Let's end this tip with a simple MIDlet that demonstrates how to
fill a List component from a record store. The records in the
record store contain the first and last names of a group of
people. The MIDlet includes a screen that lets you choose how to
sort and filter the records.
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;
// Demonstrates simple record sorting and filtering
public class EnumDemo extends MIDlet
implements CommandListener {
// Data members we need
private Display display;
private RecordStore rs;
private EnumList enumListScreen;
private SortOptions sortOptionsScreen;
private String firstName;
private String lastName;
private byte[] data = new byte[200];
private ByteArrayInputStream bin = new ByteArrayInputStream(
data );
private DataInputStream din = new DataInputStream( bin );
// Define the four commands we use
private Command exitCommand = new Command( "Exit",
Command.EXIT, 1 );
private Command sortCommand = new Command( "Sort",
Command.SCREEN, 1 );
private Command cancelCommand = new Command( "Cancel",
Command.CANCEL, 1 );
private Command okCommand = new Command( "OK", Command.OK, 1 );
// Define the sorting modes
private static final int SORT_NONE = 0;
private static final int SORT_FIRST_LAST = 1;
private static final int SORT_LAST_FIRST = 2;
// Define the filtering modes
private static final int FILTER_NONE = 0;
private static final int FILTER_STARTSWITH = 1;
private static final int FILTER_CONTAINS = 2;
// A simple class to hold the parts of a record
private static class Record {
String firstName;
String lastName;
}
// Precanned names
private static final String[][] names = {
{ "Eric", "Giguere" },
{ "John", "Doe" },
{ "Lisa", "Munro" },
{ "Stephanie", "Kwaly" },
{ "Dave", "Boyer" },
{ "Gwen", "Stephens" },
{ "Jennifer", "Lopert" },
{ "Ed", "Ort" },
};
// Constructor
public EnumDemo(){
}
// Clean up
protected void destroyApp( boolean unconditional )
throws MIDletStateChangeException {
exitMIDlet();
}
// Close the record store for now
protected void pauseApp(){
closeRecordStore();
}
// Initialize things and reopen record store if not open
protected void startApp() throws MIDletStateChangeException {
if( display == null ){ // first time called...
initMIDlet();
}
if( rs == null ){
openRecordStore();
}
}
// Once-only initialization code
private void initMIDlet(){
display = Display.getDisplay( this );
enumListScreen = new EnumList();
sortOptionsScreen = new SortOptions();
if( openRecordStore() ){
enumListScreen.resort();
display.setCurrent( enumListScreen );
}
}
// Termination code
public void exitMIDlet(){
closeRecordStore();
notifyDestroyed();
}
// Add a first-last name pair to the record store
private void addName( String first, String last,
ByteArrayOutputStream bout,
DataOutputStream dout ){
try {
dout.writeUTF( first );
dout.writeUTF( last );
dout.flush();
byte[] data = bout.toByteArray();
rs.addRecord( data, 0, data.length );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -