我有一个动作栏SearchView,我试图让用户搜索葡萄酒数据库。
我尝试在用户输入时进行搜索,就像他们输入" na"它会显示包含" na"的所有结果。等等。
这是我的菜单搜索按钮if语句:
if (id == R.id.action_wine_search) {
SearchView searchView = getActivity().findViewById(R.id.action_wine_search);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String newText) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
mCursorAdapter.getFilter().filter(newText);
//mCursorAdapter is selecting id,name,price,etc. columns from the table
wineListView.setAdapter(mCursorAdapter);
return false;
}
});
}
据我所知(我可能只是以错误的方式考虑这个)是过滤器从SearchView获取文本并将该文本应用于CursorAdapter。
但这并没有做任何事情。无论你输入什么内容,该列表都不会发生变化。
我跟着一个youtube视频为此。我不太明白它是如何应用于CursorAdapter的。
我最终自己尝试了(这也失败了,列表根本没有变化):
public boolean onQueryTextChange(String newText) {
SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();
//Selecting what details I want to put into each row in the list
String[] projection = {
WineContract.WineEntry.COLUMN_ID,
WineContract.WineEntry.COLUMN_WINE_NAME,
WineContract.WineEntry.COLUMN_WINE_PRICE,
WineContract.WineEntry.COLUMN_WINE_RATING,
WineContract.WineEntry.COLUMN_WINE_STORE,
WineContract.WineEntry.COLUMN_WINE_IMAGE,
WineContract.WineEntry.COLUMN_WINE_THUMBNAIL};
//I want to return the row where the name is equal to newText (which is what the user types into the SearchView
String selection = WineContract.WineEntry.COLUMN_WINE_NAME + " = ?";
String[] selectionArgs = {newText};
Cursor cursor = db.query(WineContract.WineEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
mCursorAdapter = new WineCursorAdapter(getActivity(), cursor);
wineListView.setAdapter(mCursorAdapter);
return false;
}
});
我可以帮助理解这是如何工作的吗?
答案 0 :(得分:1)
我查看了您关联的视频,不幸的是,该视频演示了如何以完全不同的方式实现此搜索功能。也就是说,它们使用ArrayAdapter<String>
,它具有Filter
的一些内置实现,允许它们在简单的结果列表上执行子串匹配。
不幸的是,您使用CursorAdapter
搜索数据库的情况不会以这种方式运行。 CursorAdapter
返回一个Cursor
对象,它实际上只是一个“外观”,用于检索数据库查询返回的行数据/结果。换句话说,CursorAdapter
不知道如何“过滤”任何内容,您必须指定应用过滤器时要执行的操作。例如,您需要实现以下内容:
adapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence query) {
// Run some database query, given this "query" String and return a Cursor
return searchDatabase(query);
}
});
你有一个正确的想法是你的第二段代码来实现搜索查询。但是,标准的SQLite数据库表只允许您检索与完全条件匹配的行(基本上就是您上面编写过的代码),而不是像您可能想要的那样匹配子字符串。
幸运的是,有一种方法可以在SQLite数据库中进行全文搜索,因此您可以搜索和匹配查询到子字符串和部分查询,可能是您实际想要的。您可以使用称为SQLite虚拟表的东西来实现像FTS3这样的方案来支持搜索。下面链接的官方Android文档有一个很棒的教程,它将向您展示如何实现这一目标:
https://developer.android.com/training/search/search.html
我在过去几次使用过这种方法来实现数据库搜索。这可能比您预期更改当前数据库帮助程序要多一些工作,但这是我知道如何执行此操作的方式。如果有什么事情没有意义,请告诉我!
另外,我希望考虑到我上面关于重构代码的评论,因为我确定你想要编写一个认为性能良好的应用程序!
答案 1 :(得分:0)
我不确定这是否适合我所做的所有类似的事情是有一个带有textChangedListener的EditText,它只是驱动查询,获取更新的游标并在ListView适配器上使用swapCursor。查询本身使用Like来获取所有出现的内容,例如有na。
这是监听器设置代码: -
/**************************************************************************
* addFilterListener - Add a Listener to filter the ListView
* i.e. as characters are typed then the ListView
* is filtered according to the characters input
* This is done by using LIKE '%<characters>%'
*
*/
public void addFilterListener() {
inputproductfilter.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
productfilter = DBProductsTableConstants.PRODUCTS_NAME_COL_FULL +
SQLLIKECHARSTART +
inputproductfilter.getText().toString() +
SQLLIKECHAREND;
plcsr = dbproductmethods.getExpandedProducts(productfilter,orderby);
productlistadapter.swapCursor(plcsr);
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
它使用: -
public static final String SQLLIKECHARSTART = " LIKE '%";
public static final String SQLLIKECHAREND = "%' ";
和以下
public static final String SQLAS = " AS ";
并非所有与此相关的 getExpandedproducts
: -
/**************************************************************************
*
* @param filter filter string less WHERE keyword
* @param order order String less ORDER and BY kewords
* @return Cursor containing Expanded products
*/
Cursor getExpandedProducts(String filter, String order) {
Cursor rv;
String[] columns = new String[] {
DBProductsTableConstants.PRODUCTS_ID_COL_FULL,
DBProductsTableConstants.PRODUCTS_NAME_COL_FULL,
DBProductsTableConstants.PRODUCTS_NOTES_COL_FULL,
DBProductsTableConstants.PRODUCTS_STORAGEORDER_COL_FULL,
DBProductsTableConstants.PRODUCTS_STORAGEREF_COL_FULL,
DBStorageTableConstants.STORAGE_ID_COL_FULL +
SQLAS + DBStorageTableConstants.STORAGE_ALTID_COL,
DBStorageTableConstants.STORAGE_NAME_COL_FULL,
DBStorageTableConstants.STORAGE_ORDER_COL_FULL
};
String table = DBProductsTableConstants.PRODUCTS_TABLE +
SQLLEFTJOIN +
DBStorageTableConstants.STORAGE_TABLE +
SQLON +
DBProductsTableConstants.PRODUCTS_STORAGEREF_COL_FULL +
" = " +
DBStorageTableConstants.STORAGE_ID_COL_FULL;
rv = db.query(table,columns,filter,null,null,null,order);
return rv;
}
e.g。完整清单: -
然后在过滤器中输入 na : -