Android开发:如何在ListView中搜索多词语句而非单个单词
Android ListView多词语搜索解决方案
当前代码仅支持单个单词搜索,无法处理多词语句的搜索需求,以下是针对性的修复方案:
问题分析
现有代码将多词拆分为OR条件,导致只要包含任意一个关键词的条目都会被返回,而非匹配所有关键词;同时直接拼接SQL字符串存在注入风险,且空输入时未恢复原始列表。
修复步骤
1. 调整搜索逻辑(匹配所有关键词)
将原代码中的OR改为AND,确保只有包含所有搜索关键词的条目才会被筛选出来;若需要支持“包含任意关键词”,可保留OR。
2. 使用参数化查询避免SQL注入
直接拼接字符串存在安全风险,改用参数化查询绑定关键词。
3. 完善空输入处理
当搜索框为空时,恢复显示原始列表,提升用户体验。
4. 统一列表点击事件
避免重复设置OnItemClickListener,简化代码逻辑。
修改后的代码
MainActivity.java关键部分修改
etSearchKey.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { String search_by = "name"; String key = etSearchKey.getText().toString().trim(); // 空输入时恢复原始列表 if (key.isEmpty()) { resetOriginalList(); return; } String[] keys = key.split("\\s+"); StringBuilder queryBuilder = new StringBuilder(); // 构建AND条件的查询语句 for (int i = 0; i < keys.length; i++) { if (i > 0) { queryBuilder.append(" AND "); } queryBuilder.append(search_by).append(" LIKE ?"); } // 传递参数数组,避免SQL注入 showResultOfSearch(queryBuilder.toString(), keys); } @Override public void afterTextChanged(Editable s) {} }); // 新增恢复原始列表的方法 private void resetOriginalList() { String[] from = {"name"}; int[] to = {R.id.row_hezb_name}; SimpleAdapter adb = new SimpleAdapter(getBaseContext(), books_list, R.layout.row_hezb, from, to); contentListView.setAdapter(adb); // 绑定原始列表的点击事件 contentListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent i = new Intent(getBaseContext(), List_hezbha.class); String my_id = books_list.get(position).get("name").toString(); i.putExtra("name", my_id); startActivity(i); } }); } // 修改showResultOfSearch方法,支持参数传递 public void showResultOfSearch(String query, String[] params) { db.open(); contentListView.setAdapter(null); // 数据库方法改为接收查询语句和参数数组 resultBooks = db.getTableOfResultsOfSearchhezb(query, params); db.close(); if (resultBooks.size() < 1) { // 无结果时清空列表,也可添加空提示视图 contentListView.setAdapter(null); return; } String[] from = {"name"}; int[] to = {R.id.row_hezb_name}; SimpleAdapter adb = new SimpleAdapter(getBaseContext(), resultBooks, R.layout.row_hezb, from, to); contentListView.setAdapter(adb); contentListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { try { etSearchKey.setText(""); etSearchKey.clearFocus(); Intent i = new Intent(getBaseContext(), List_hezbha.class); String my_id = resultBooks.get(position).get("name").toString(); i.putExtra("name", my_id); startActivity(i); } catch (Exception ex) { ex.printStackTrace(); } } }); }
数据库类(database.java)对应修改
需要修改getTableOfResultsOfSearchhezb方法,支持参数化查询:
public List<HashMap<String, Object>> getTableOfResultsOfSearchhezb(String query, String[] params) { List<HashMap<String, Object>> list = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); // 为每个参数添加通配符,实现模糊匹配 String[] likeParams = new String[params.length]; for (int i = 0; i < params.length; i++) { likeParams[i] = "%" + params[i] + "%"; } // 使用rawQuery传递参数 Cursor cursor = db.rawQuery("SELECT * FROM your_table_name WHERE " + query, likeParams); if (cursor.moveToFirst()) { do { HashMap<String, Object> map = new HashMap<>(); map.put("name", cursor.getString(cursor.getColumnIndex("name"))); // 其他字段按需添加 list.add(map); } while (cursor.moveToNext()); } cursor.close(); return list; }
额外优化建议
- 添加搜索防抖:使用
Handler延迟执行搜索逻辑,避免输入过程中频繁触发数据库查询。 - 大小写不敏感搜索:在SQL语句中添加
COLLATE NOCASE,实现忽略大小写的模糊匹配。
内容的提问来源于stack exchange,提问作者Shahin Sadeghi
相关产品推荐
相关产品推荐

