我正在尝试使用RecordFilter界面过滤一些记录。在我的应用程序中,我有几个类似于此的界面,用户可以在其上输入ID或名称(他/她可以输入两者或两者都不输入)
这是我到目前为止所做的:
客户过滤器。
如果用户没有输入ID,我将0作为默认值传递,这就是我评估customerID!=0
public class CustomerFilter implements RecordFilter {
private String mName_Filter;
private int mID_Filter;
public CustomerFilter(String name_Filter, int id_Filter) {
this.mName_Filter = name_Filter.toLowerCase();
this.mID_Filter = id_Filter;
}
public boolean matches(byte[] candidate) {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(candidate);
DataInputStream dis = new DataInputStream(bis);
int customerID = dis.readInt();
String customerName = dis.readUTF().toLowerCase();
if ((customerName != null && customerName.indexOf(mName_Filter) != -1) && (customerID != 0 && customerID == mID_Filter))
return true;
if (customerName != null && customerName.indexOf(mName_Filter) != -1 && customerID == 0)
return true;
if (customerName == null && (customerID != 0 && customerID == mID_Filter))
return true;
if (customerName == null && customerID == 0)
return true;
} catch (IOException ex) {
//What's the point in catching a exception here???
}
return false;
}
}
搜索方法:
注意:此方法位于我称为“RMSCustomer”的类中,我在其中处理与RMS访问相关的所有内容。搜索方法接收两个参数(id和name)并使用它们来实例化过滤器。
public Customer[] search(int id, String name) throws RecordStoreException, IOException {
RecordStore rs = null;
RecordEnumeration recEnum = null;
Customer[] customerList = null;
try {
rs = RecordStore.openRecordStore(mRecordStoreName, true);
if (rs.getNumRecords() > 0) {
CustomerFilter filter = new CustomerFilter(name, id);
try {
recEnum = rs.enumerateRecords(filter, null, false);
if (recEnum.numRecords() > 0) {
customerList = new Customer[recEnum.numRecords()];
int counter = 0;
while (recEnum.hasNextElement()) {
Customer cust;
int idRecord = recEnum.nextRecordId();
byte[] filterRecord = rs.getRecord(idRecord);
cust = parseRecord(filterRecord);
cust.idRecord = idRecord;
customerList[counter] = cust;
counter++;
}
}
else{
customerList = new Customer[0];
//How to send a message to the midlet from here
//saying something like "No Record Exists.Please select another filter"
}
} finally {
recEnum.destroy();
}
}
else{
//How to send a message to the midlet from here
//saying something like "No Record Exists.Please Add record"
}
} finally {
rs.closeRecordStore();
}
return customerList;
}
即使上面显示的代码有效,我仍然有一些问题/问题:
在过滤器:
中1)如何改进评估过滤器(name,id)可能值的代码?如果我有更多过滤器怎么办?我是否必须测试所有可能的组合?
2)如果用户既没有输入ID也没有输入名称,我应该显示所有记录还是应该显示消息“请输入名称或ID”?在这种情况下你会做什么?
3)为什么在我无法做任何事情的时候必须在过滤器中放一个try-catch?我不能在那里显示任何警报,或者我可以吗?
在搜索方法中:
1)如何从该方法向用户显示正确的消息?像“没有记录”之类的东西(参见我的代码中的“ELSE”部分
抱歉,如果我问了太多问题,那就是有任何完整的过滤器示例。
提前致谢
答案 0 :(得分:2)
如何改进评估可能值的代码 过滤器(名称,ID)?
ID是记录中的第一个字段,也是最快搜索的字段。如果Id匹配,那么客户名称并不重要。通常,您将查找ID匹配或客户名称匹配的记录,因此一旦ID匹配,您就可以返回true。这是我对CustomerFilter
类的提议:
public class CustomerFilter implements RecordFilter {
private String mName_Filter;
//Use Integer instead of int.
//This way we can use null instead of zero if the user didn't type an ID.
//This allows us to store IDs with values like 0, -1, etc.
//It is a bit less memory efficient,
//but you are not creating hundreds of filters, are you? (If you are, don't).
private Integer mID_Filter;
public CustomerFilter(String name_Filter, Integer id_Filter) {
this.mName_Filter = normalizeString(mName_Filter);
this.mID_Filter = id_Filter;
}
//You should move this function to an StringUtils class and make it public.
//Other filters might need it in the future.
private static String normalizeString(final String s){
if(s != null){
//Warning: you might want to replace accentuated chars as well.
return s.toLowerCase();
}
return null;
}
public boolean matches(byte[] candidate) {
ByteArrayInputStream bis = new ByteArrayInputStream(candidate);
DataInputStream dis = new DataInputStream(bis);
try {
if(mID_Filter != null){
//If the ID is unique, and the search is ID OR other fields, this is fine
int customerID = dis.readInt();
if(mID_Filter.intValue == customerID){
return true;
} else {
return false;
}
}
if(mName_Filter != null){
String customerName = normalizeString(dis.readUTF());
if(customerName != null && customerName.indexOf(mName_Filter) != -1){
return true;
}
}
if(mID_Filter == null && mName_Filter == null){
return true; // No filtering, every record matches.
}
} catch (IOException ex) {
//Never swallow exceptions.
//Even if you are using an underlying ByteArrayInputStream, an exception
//can still be thrown when reading from DataInputStream if you try to read
//fields that do not exists.
//But even if no exceptions were ever thrown, never swallow exceptions :)
System.err.println(ex);
//Optional: throw ex;
} finally {
//Always close streams.
if(bis != null){
try {
bis.close();
} catch(IOException ioe){
System.err.println(ioe);
}
}
if(dis != null){
try {
dis.close();
} catch(IOException ioe){
System.err.println(ioe);
}
}
}
return false;
}
}
如果我有更多过滤器怎么办?我是否必须测试所有可能的 组合??
这取决于你的项目。通常,ID是唯一的,并且不存在具有相同ID的两个记录。在这种情况下,您应该明确地设计屏幕,以便用户理解他键入了Id,或者他填写了其他字段。条件是这样的:
idMatches OR (field1Matches AND field2Matches AND ... fieldNMatches)
如果用户没有输入任何内容,则会返回所有记录。
但是,这又是一个用户体验问题,我不知道它是否符合您的要求。
从编程的角度来看,很明显,你添加的字段越多,你的过滤器就会变得越乱。为防止出现这种情况,您可以使用Decorator,Composite甚至Chain of responsibility等模式。尽管如此,你可能不得不换取良好的设计性能。
如果用户既未输入ID也未输入名称,我是否应该显示 所有记录或我应该显示消息"请输入名称或 ID" ??在这种情况下你会做什么?
这取决于。有没有其他方法可以查看所有记录?如果是,则显示消息。
为什么我不能在过滤器中添加try-catch 那里有什么?我无法显示任何警报或我可以吗?
你不应该。此类仅负责过滤,而不是与用户交互。您仍然可以从catch子句中记录错误,然后再次抛出异常。这会将异常传播到RMSCustomer.search
,因此无论客户端代码调用该函数将以与处理该方法抛出的其他异常相同的方式处理异常。但是保持finally子句关闭流。
如何从该方法向用户显示正确的消息? 喜欢"没有记录" (参见" ELSE"我的代码中的部分)
您不应该从RMSCustomer类中执行与GUI相关的任何操作(如显示对话框)。即使您没有使用模型 - 视图 - 控制器模式,您仍然希望让您的课程专注于单一职责(管理记录)。这称为Single responsibility principle。
保持您的类与GUI隔离将允许您测试它并在没有GUI的环境中重用它。
当结果为零时,屏幕应处理无记录案例。一个长度== 0的数组在这里很好,屏幕将显示"没有结果"信息。对于其他类型的错误,您可以扩展Exception类并从RecordParsingException
方法中抛出您自己的自定义异常,即:RMSCustomer.search
。然后,屏幕类将以用户的语言将不同的异常映射到错误消息。