使用SearchView搜索SQLite数据库

时间:2017-10-26 22:21:46

标签: android sqlite

我有一个动作栏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;
            }
        });

我可以帮助理解这是如何工作的吗?

2 个答案:

答案 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。完整清单: -

enter image description here

然后在过滤器中输入 na : -

enter image description here