Android:为SQLite加载的ListView添加SearchView搜索功能(求完整代码)
Hey there! I see you’ve already got your custom ImageCursorAdapter working to load a ListView with images and text from SQLite—great job! Let’s add that SearchView functionality so users can filter your list easily. I’ll provide the full implementation, including layout setup, search logic, and adjusted SQL queries.
Step 1: Add SearchView to Your Activity's Menu
First, create a menu resource file to include the SearchView. Create res/menu/main_menu.xml:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_search" android:title="Search" android:icon="@android:drawable/ic_menu_search" app:showAsAction="ifRoom|collapseActionView" app:actionViewClass="android.widget.SearchView" /> </menu>
Step 2: Full Implementation of Your ImageCursorAdapter
Let’s complete your ImageCursorAdapter (since your snippet was cut off). This adapter will handle converting the byte array from SQLite into a Bitmap for the ImageView:
import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; public class ImageCursorAdapter extends SimpleCursorAdapter { private Context context; private int layout; public ImageCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); this.context = context; this.layout = layout; } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { return LayoutInflater.from(context).inflate(layout, parent, false); } @Override public void bindView(View view, Context context, Cursor cursor) { super.bindView(view, context, cursor); // Get references to your row views ImageView imageView = view.findViewById(R.id.list_item_image); TextView textView = view.findViewById(R.id.list_item_text); // Fetch data from cursor (replace column names with your actual ones) byte[] imageBytes = cursor.getBlob(cursor.getColumnIndexOrThrow("image")); String itemText = cursor.getString(cursor.getColumnIndexOrThrow("item_name")); // Convert byte array to Bitmap for ImageView if (imageBytes != null) { Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); imageView.setImageBitmap(bitmap); } // Set text for TextView textView.setText(itemText); } }
Step 3: Database Helper Class with Search Query Logic
Update your SQLite helper to include a method that returns filtered results based on the search query. Here’s a complete DBHelper.java:
import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DBHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "items_db.db"; private static final int DATABASE_VERSION = 1; // Replace with your actual table and column names private static final String TABLE_ITEMS = "items"; private static final String COLUMN_ID = "_id"; private static final String COLUMN_IMAGE = "image"; private static final String COLUMN_ITEM_NAME = "item_name"; public DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { String createTableQuery = "CREATE TABLE " + TABLE_ITEMS + " (" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_IMAGE + " BLOB, " + COLUMN_ITEM_NAME + " TEXT NOT NULL)"; db.execSQL(createTableQuery); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_ITEMS); onCreate(db); } // Get all items for initial list load public Cursor getAllItems() { SQLiteDatabase db = this.getReadableDatabase(); return db.query(TABLE_ITEMS, null, null, null, null, null, COLUMN_ITEM_NAME + " ASC"); } // Get filtered items based on search query public Cursor getFilteredItems(String searchQuery) { SQLiteDatabase db = this.getReadableDatabase(); String selection = COLUMN_ITEM_NAME + " LIKE ?"; String[] selectionArgs = new String[]{"%" + searchQuery + "%"}; return db.query(TABLE_ITEMS, null, selection, selectionArgs, null, null, COLUMN_ITEM_NAME + " ASC"); } }
Step 4: Main Activity with SearchView Integration
Finally, update your main activity to handle the SearchView, load data, and refresh the ListView when the search query changes:
import android.database.Cursor; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.ListView; import android.widget.SearchView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private DBHelper dbHelper; private ImageCursorAdapter listAdapter; private ListView itemListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); itemListView = findViewById(R.id.item_list_view); dbHelper = new DBHelper(this); // Initialize adapter with all items Cursor initialCursor = dbHelper.getAllItems(); String[] fromColumns = {"item_name", "image"}; // Match your column names int[] toViews = {R.id.list_item_text, R.id.list_item_image}; // Match your row view IDs listAdapter = new ImageCursorAdapter(this, R.layout.list_item_row, initialCursor, fromColumns, toViews, 0); itemListView.setAdapter(listAdapter); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_menu, menu); MenuItem searchItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) searchItem.getActionView(); // Handle search input changes searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { updateListWithFilter(query); return true; } @Override public boolean onQueryTextChange(String newText) { updateListWithFilter(newText); return true; } }); return true; } private void updateListWithFilter(String query) { // Close old cursor to prevent memory leaks Cursor oldCursor = listAdapter.getCursor(); if (oldCursor != null && !oldCursor.isClosed()) { oldCursor.close(); } // Get new filtered cursor Cursor newCursor; if (query.trim().isEmpty()) { newCursor = dbHelper.getAllItems(); } else { newCursor = dbHelper.getFilteredItems(query); } // Update adapter with new data listAdapter.swapCursor(newCursor); } @Override protected void onDestroy() { super.onDestroy(); // Clean up resources dbHelper.close(); Cursor cursor = listAdapter.getCursor(); if (cursor != null && !cursor.isClosed()) { cursor.close(); } } }
Quick Reminders:
- Replace all placeholder names (like
list_item_row,item_list_view,item_name) with your actual layout IDs and database column names. - Your
list_item_row.xmlshould contain anImageView(with IDlist_item_image) andTextView(with IDlist_item_text) for each list row. - For better lifecycle management, consider using
CursorLoaderinstead of directly managing cursors later on—but this implementation is beginner-friendly and works perfectly for your use case.
内容的提问来源于stack exchange,提问作者Ashok Thallapally

