如何改进自动完成文本小部件中的搜索
How do I improve Searching in an AutoComplete text widget
我有两个 AutoCompleteTextView,其中填充了来自 sqlite 数据库的数据。我从 ERP 服务器中提取信息并将其本地存储在 sqlite 数据库中,并像这样填充文本视图:
equipment = (AutoCompleteTextView) findViewById(R.id.equipmentAutoCompleteTextView);
if(equipment.getText().toString().length() == 0){
equipment.setError("Equipment is required");
}
FieldInstallationDB sqlitedb1 = new FieldInstallationDB(this);
sqlitedb1.openForRead();
String[] items = sqlitedb.getAllItemNames();
for(int i = 0; i < items.length; i++)
{
Log.i(this.toString(), items[i]);
}
ArrayAdapter<String> adapter1 = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, items);
equipment.setAdapter(adapter1);
equipment.setThreshold(1);
这里:
customerName = (AutoCompleteTextView) findViewById(R.id.customerNameAutoCompleteTextView);
if(customerName.getText().toString().length() == 0){
customerName.setError("Customer Name is required");
}
FieldInstallationDB sqlitedb = new FieldInstallationDB(this);
sqlitedb.openForRead();
String[] accounts = sqlitedb.getAllCustNames();
for(int i = 0; i < accounts.length; i++)
{
Log.i(this.toString(), accounts[i]);
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, accounts);
customerName.setAdapter(adapter);
customerName.setThreshold(1);
假设我有这些:
- 黑勺子
- 红勺子
- 一匙
然后我开始输入 "spo",我想查看列出的所有三个项目以进行选择。相反,我只得到 "Spoonful" 出现。我如何让它识别并显示所有具有字母 "spo"?
的实例(项目)
更新:
在对我的问题发表第一条评论后,我阅读了更多文章并将我的代码更新为如下所示:
equipment = (AutoCompleteTextView) findViewById(R.id.equipmentAutoCompleteTextView);
if(equipment.getText().toString().length() == 0){
equipment.setError("Equipment is required");
}
FieldInstallationDB sqlitedb1 = new FieldInstallationDB(this);
sqlitedb1.openForRead();
String[] items = sqlitedb1.getAllItemNames();
for(int i = 0; i < items.length; i++)
{
Log.i(this.toString(), items[i]);
}
equipment.setThreshold(1);
SimpleCursorAdapter itemNameAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_dropdown_item_1line, null, items, toView, 0);
itemNameAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return suggestItemCompletions(constraint);
}
});
itemNameAdapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter() {
public CharSequence convertToString(Cursor cur) {
int index = cur.getColumnIndex(FieldInstallationDB.ITEM_NAME);
return cur.getString(index);
}});
equipment.setAdapter(itemNameAdapter);
这里是activityclass中写的suggestitemcompletions方法:
public Cursor suggestItemCompletions(CharSequence str) {
return getContentResolver().query(null, new String[] {FieldInstallationDB.ITEM_NAME}, "(" + FieldInstallationDB.ITEM_NAME + " LIKE ? ", new String[] {"%" + str + "%"}, null);
}
这建议使用 getContentResolver(),这对我来说没有意义,因为我访问的是我的应用程序的数据库,而不是另一个应用程序的数据库。结果它不起作用,因为我将 URI 参数设置为空,因为我的数据库 table 没有 URI。但是,如果我决定不使用 getContentResolver() 并直接查询 FieldInstallationDB,我会在 .query() 处收到错误消息,说无法解析方法。
更新二:
我按照建议使用了 rawQuery() 并且有效:
public Cursor suggestItemCompletions(CharSequence str) {
fieldInstDatabase = openForRead();
String sql = "Select "+ ITEM_NAME+ " FROM "+ TABLE_EQUIPMENT+ " WHERE "+ ITEM_NAME + " LIKE ?";
String[] selectArgs = new String[]{ "%" + str + "%"};
return fieldInstDatabase.rawQuery(sql,selectArgs);
}
这个方法在我的数据库 class 中,我在主 activity 中调用它:
itemNameAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return sqlitedb1.suggestItemCompletions(constraint);
}
});
除了我在这里收到 IllegalArgumentException:
01-10 13:07:08.792 5361-5361/com.example.sweetiean.stlfieldinstallation1 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.sweetiean.stlfieldinstallation1, PID: 5361
java.lang.IllegalArgumentException: column 'Bag(TypeC) :
5900016009' does not exist
这是有道理的,因为“Bag(TypeC):
5900016009" 不是列,它是数据库中 ITEM NAME 列中的第一项。
我不知道为什么它读取第一项作为列名。我已尝试调试,但无法进入
public Cursor runQuery(CharSequence constraint) {
return sqlitedb1.suggestItemCompletions(constraint);
}
正如评论中所建议的,由于我的 SimpleCursorAdapter 中的 from
参数,此处发生了 IllegalArgumentException。 SimpleCursorAdapter 的 from
和 to
参数需要分别填充 table 和文本视图的列名。
在我的例子中,我使用从数据库中获取的项目的字符串数组填充 from
参数:
String[] items = sqlitedb1.getAllItemNames();
for(int i = 0; i < items.length; i++)
{
Log.i(this.toString(), items[i]);
}
equipment.setThreshold(1);
SimpleCursorAdapter itemNameAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_dropdown_item_1line, null, items, toView, 0);
更正为:
SimpleCursorAdapter itemNameAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_dropdown_item_1line, null, fromCol, toView, 0);
将 fromCol
定义为 final static String[] fromCol = new String[] { FieldInstallationDB.ITEM_NAME };
修复了它。
我有两个 AutoCompleteTextView,其中填充了来自 sqlite 数据库的数据。我从 ERP 服务器中提取信息并将其本地存储在 sqlite 数据库中,并像这样填充文本视图:
equipment = (AutoCompleteTextView) findViewById(R.id.equipmentAutoCompleteTextView);
if(equipment.getText().toString().length() == 0){
equipment.setError("Equipment is required");
}
FieldInstallationDB sqlitedb1 = new FieldInstallationDB(this);
sqlitedb1.openForRead();
String[] items = sqlitedb.getAllItemNames();
for(int i = 0; i < items.length; i++)
{
Log.i(this.toString(), items[i]);
}
ArrayAdapter<String> adapter1 = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, items);
equipment.setAdapter(adapter1);
equipment.setThreshold(1);
这里:
customerName = (AutoCompleteTextView) findViewById(R.id.customerNameAutoCompleteTextView);
if(customerName.getText().toString().length() == 0){
customerName.setError("Customer Name is required");
}
FieldInstallationDB sqlitedb = new FieldInstallationDB(this);
sqlitedb.openForRead();
String[] accounts = sqlitedb.getAllCustNames();
for(int i = 0; i < accounts.length; i++)
{
Log.i(this.toString(), accounts[i]);
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, accounts);
customerName.setAdapter(adapter);
customerName.setThreshold(1);
假设我有这些:
- 黑勺子
- 红勺子
- 一匙
然后我开始输入 "spo",我想查看列出的所有三个项目以进行选择。相反,我只得到 "Spoonful" 出现。我如何让它识别并显示所有具有字母 "spo"?
的实例(项目)更新:
在对我的问题发表第一条评论后,我阅读了更多文章并将我的代码更新为如下所示:
equipment = (AutoCompleteTextView) findViewById(R.id.equipmentAutoCompleteTextView);
if(equipment.getText().toString().length() == 0){
equipment.setError("Equipment is required");
}
FieldInstallationDB sqlitedb1 = new FieldInstallationDB(this);
sqlitedb1.openForRead();
String[] items = sqlitedb1.getAllItemNames();
for(int i = 0; i < items.length; i++)
{
Log.i(this.toString(), items[i]);
}
equipment.setThreshold(1);
SimpleCursorAdapter itemNameAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_dropdown_item_1line, null, items, toView, 0);
itemNameAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return suggestItemCompletions(constraint);
}
});
itemNameAdapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter() {
public CharSequence convertToString(Cursor cur) {
int index = cur.getColumnIndex(FieldInstallationDB.ITEM_NAME);
return cur.getString(index);
}});
equipment.setAdapter(itemNameAdapter);
这里是activityclass中写的suggestitemcompletions方法:
public Cursor suggestItemCompletions(CharSequence str) {
return getContentResolver().query(null, new String[] {FieldInstallationDB.ITEM_NAME}, "(" + FieldInstallationDB.ITEM_NAME + " LIKE ? ", new String[] {"%" + str + "%"}, null);
}
这建议使用 getContentResolver(),这对我来说没有意义,因为我访问的是我的应用程序的数据库,而不是另一个应用程序的数据库。结果它不起作用,因为我将 URI 参数设置为空,因为我的数据库 table 没有 URI。但是,如果我决定不使用 getContentResolver() 并直接查询 FieldInstallationDB,我会在 .query() 处收到错误消息,说无法解析方法。
更新二:
我按照建议使用了 rawQuery() 并且有效:
public Cursor suggestItemCompletions(CharSequence str) {
fieldInstDatabase = openForRead();
String sql = "Select "+ ITEM_NAME+ " FROM "+ TABLE_EQUIPMENT+ " WHERE "+ ITEM_NAME + " LIKE ?";
String[] selectArgs = new String[]{ "%" + str + "%"};
return fieldInstDatabase.rawQuery(sql,selectArgs);
}
这个方法在我的数据库 class 中,我在主 activity 中调用它:
itemNameAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return sqlitedb1.suggestItemCompletions(constraint);
}
});
除了我在这里收到 IllegalArgumentException:
01-10 13:07:08.792 5361-5361/com.example.sweetiean.stlfieldinstallation1 E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.sweetiean.stlfieldinstallation1, PID: 5361 java.lang.IllegalArgumentException: column 'Bag(TypeC) : 5900016009' does not exist
这是有道理的,因为“Bag(TypeC): 5900016009" 不是列,它是数据库中 ITEM NAME 列中的第一项。
我不知道为什么它读取第一项作为列名。我已尝试调试,但无法进入
public Cursor runQuery(CharSequence constraint) {
return sqlitedb1.suggestItemCompletions(constraint);
}
正如评论中所建议的,由于我的 SimpleCursorAdapter 中的 from
参数,此处发生了 IllegalArgumentException。 SimpleCursorAdapter 的 from
和 to
参数需要分别填充 table 和文本视图的列名。
在我的例子中,我使用从数据库中获取的项目的字符串数组填充 from
参数:
String[] items = sqlitedb1.getAllItemNames();
for(int i = 0; i < items.length; i++)
{
Log.i(this.toString(), items[i]);
}
equipment.setThreshold(1);
SimpleCursorAdapter itemNameAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_dropdown_item_1line, null, items, toView, 0);
更正为:
SimpleCursorAdapter itemNameAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_dropdown_item_1line, null, fromCol, toView, 0);
将 fromCol
定义为 final static String[] fromCol = new String[] { FieldInstallationDB.ITEM_NAME };
修复了它。