如何在基于SQLite的Android RecyclerView中实现SearchView搜索功能
实现步骤
1. 修改MyDatabaseHelper类,添加搜索查询方法
在MyDatabaseHelper.java中新增模糊搜索方法,支持按患者姓名、疾病匹配:
// 添加到MyDatabaseHelper类中 public Cursor searchPatients(String keyword) { SQLiteDatabase db = this.getReadableDatabase(); String query = "SELECT * FROM " + TABLE_NAME + " WHERE " + COLUMN_NAME + " LIKE ? OR " + COLUMN_DISEASE + " LIKE ?"; String[] selectionArgs = new String[]{"%" + keyword + "%", "%" + keyword + "%"}; return db.rawQuery(query, selectionArgs); }
2. 修改CustomAdapter类,实现筛选逻辑
让Adapter实现Filterable接口,区分全量原始数据和筛选后数据,实现搜索过滤逻辑:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> implements Filterable { private Context context; // 全量原始数据 private ArrayList<String> originalId, originalName, originalDisease, originalMedicine, originalMobile, originalAddress, originalDay, originalMonth, originalYear; // 筛选后展示数据 private ArrayList<String> filteredId, filteredName, filteredDisease, filteredMedicine, filteredMobile, filteredAddress, filteredDay, filteredMonth, filteredYear; CustomAdapter(Context context, ArrayList<String> _id, ArrayList<String> name, ArrayList<String> disease, ArrayList<String> medicine, ArrayList<String> mobile, ArrayList<String> address, ArrayList<String> day, ArrayList<String> month, ArrayList<String> year){ this.context = context; this.originalId = _id; this.originalName = name; this.originalDisease = disease; this.originalMedicine = medicine; this.originalMobile = mobile; this.originalAddress = address; this.originalDay = day; this.originalMonth = month; this.originalYear = year; // 初始状态下筛选数据等于全量数据 this.filteredId = _id; this.filteredName = name; this.filteredDisease = disease; this.filteredMedicine = medicine; this.filteredMobile = mobile; this.filteredAddress = address; this.filteredDay = day; this.filteredMonth = month; this.filteredYear = year; } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(context); View view = inflater.inflate(R.layout.my_row, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { // 绑定筛选后的数据 holder.id_txt.setText(String.valueOf(filteredId.get(position))); holder.name_txt.setText(String.valueOf(filteredName.get(position))); holder.disease_txt.setText(String.valueOf(filteredDisease.get(position))); holder.medicine_txt.setText(String.valueOf(filteredMedicine.get(position))); holder.mobile_txt.setText(String.valueOf(filteredMobile.get(position))); holder.address_txt.setText(String.valueOf(filteredAddress.get(position))); holder.day_txt.setText(String.valueOf(filteredDay.get(position))); holder.month_txt.setText(String.valueOf(filteredMonth.get(position))); holder.year_txt.setText(String.valueOf(filteredYear.get(position))); } @Override public int getItemCount() { return filteredId.size(); } // 实现过滤逻辑 @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { String searchKey = constraint.toString().toLowerCase().trim(); if(searchKey.isEmpty()){ // 搜索为空时返回全量数据 filteredId = originalId; filteredName = originalName; filteredDisease = originalDisease; filteredMedicine = originalMedicine; filteredMobile = originalMobile; filteredAddress = originalAddress; filteredDay = originalDay; filteredMonth = originalMonth; filteredYear = originalYear; }else{ ArrayList<String> tempId = new ArrayList<>(); ArrayList<String> tempName = new ArrayList<>(); ArrayList<String> tempDisease = new ArrayList<>(); ArrayList<String> tempMedicine = new ArrayList<>(); ArrayList<String> tempMobile = new ArrayList<>(); ArrayList<String> tempAddress = new ArrayList<>(); ArrayList<String> tempDay = new ArrayList<>(); ArrayList<String> tempMonth = new ArrayList<>(); ArrayList<String> tempYear = new ArrayList<>(); for(int i=0; i<originalId.size(); i++){ // 匹配姓名或疾病,不区分大小写 if(originalName.get(i).toLowerCase().contains(searchKey) || originalDisease.get(i).toLowerCase().contains(searchKey)){ tempId.add(originalId.get(i)); tempName.add(originalName.get(i)); tempDisease.add(originalDisease.get(i)); tempMedicine.add(originalMedicine.get(i)); tempMobile.add(originalMobile.get(i)); tempAddress.add(originalAddress.get(i)); tempDay.add(originalDay.get(i)); tempMonth.add(originalMonth.get(i)); tempYear.add(originalYear.get(i)); } } filteredId = tempId; filteredName = tempName; filteredDisease = tempDisease; filteredMedicine = tempMedicine; filteredMobile = tempMobile; filteredAddress = tempAddress; filteredDay = tempDay; filteredMonth = tempMonth; filteredYear = tempYear; } FilterResults results = new FilterResults(); results.values = filteredId; return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { notifyDataSetChanged(); } }; } public class MyViewHolder extends RecyclerView.ViewHolder { TextView id_txt, name_txt, disease_txt, medicine_txt, mobile_txt, address_txt, day_txt, month_txt, year_txt; public MyViewHolder(@NonNull View itemView) { super(itemView); id_txt = itemView.findViewById(R.id.id_txt); name_txt = itemView.findViewById(R.id.name_txt); disease_txt = itemView.findViewById(R.id.disease_txt); medicine_txt = itemView.findViewById(R.id.medicine_txt); mobile_txt = itemView.findViewById(R.id.mobile_txt); address_txt = itemView.findViewById(R.id.address_txt); day_txt = itemView.findViewById(R.id.day_txt); month_txt = itemView.findViewById(R.id.month_txt); year_txt = itemView.findViewById(R.id.year_txt); } } }
3. 新增SearchView到activity_main布局
在主页面布局中添加搜索控件,放在RecyclerView上方:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <SearchView android:id="@+id/searchView" android:layout_width="match_parent" android:layout_height="wrap_content" android:queryHint="搜索患者姓名/疾病" android:iconifiedByDefault="false" android:padding="8dp"/> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/add_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@android:drawable/ic_menu_add"/> </LinearLayout>
4. 修改MainActivity类,关联搜索逻辑
在MainActivity中绑定SearchView监听,同时新增onResume方法刷新数据,保证新增患者后数据同步:
public class MainActivity extends AppCompatActivity { RecyclerView recyclerView; FloatingActionButton add_button; SearchView searchView; // 新增搜索控件变量 MyDatabaseHelper myDB; ArrayList<String> _id, name, disease, medicine, mobile, address, day, month, year; CustomAdapter customAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.recyclerView); add_button = findViewById(R.id.add_button); searchView = findViewById(R.id.searchView); // 绑定搜索控件 add_button.setOnClickListener(v -> { Intent intent = new Intent(MainActivity.this, AddActivity.class); startActivity(intent); }); myDB = new MyDatabaseHelper(MainActivity.this); _id = new ArrayList<>(); name = new ArrayList<>(); disease = new ArrayList<>(); medicine = new ArrayList<>(); mobile = new ArrayList<>(); address = new ArrayList<>(); day = new ArrayList<>(); month = new ArrayList<>(); year = new ArrayList<>(); storeDataInArrays(); customAdapter = new CustomAdapter(MainActivity.this, _id, name, disease, medicine, mobile, address, day, month, year); recyclerView.setAdapter(customAdapter); recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); // 设置搜索监听 searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { customAdapter.getFilter().filter(query); return false; } @Override public boolean onQueryTextChange(String newText) { customAdapter.getFilter().filter(newText); return false; } }); } // 新增页面回到前台时刷新数据 @Override protected void onResume() { super.onResume(); _id.clear(); name.clear(); disease.clear(); medicine.clear(); mobile.clear(); address.clear(); day.clear(); month.clear(); year.clear(); storeDataInArrays(); customAdapter = new CustomAdapter(MainActivity.this, _id, name, disease, medicine, mobile, address, day, month, year); recyclerView.setAdapter(customAdapter); // 保留当前搜索状态 if(!searchView.getQuery().toString().isEmpty()){ customAdapter.getFilter().filter(searchView.getQuery().toString()); } } void storeDataInArrays(){ Cursor cursor = myDB.readAllData(); if(cursor.getCount() == 0){ Toast.makeText(this, "No data.", Toast.LENGTH_SHORT).show(); }else{ while (cursor.moveToNext()){ _id.add(cursor.getString(0)); name.add(cursor.getString(1)); disease.add(cursor.getString(2)); medicine.add(cursor.getString(3)); mobile.add(String.valueOf(cursor.getLong(4))); address.add(cursor.getString(5)); day.add(cursor.getString(6)); month.add(cursor.getString(7)); year.add(cursor.getString(8)); } } } }
如需扩展搜索范围(比如支持手机号、地址搜索),只需修改CustomAdapter的过滤逻辑,新增对应字段的匹配判断即可。
内容的提问来源于stack exchange,提问作者Tejas Dalvi
相关产品推荐
相关产品推荐

