Android自定义Adapter无法过滤MySQL数据源数据求助
Hey there! Let's fix your SearchView filtering issue step by step. I’ve gone through your code and spotted a few key gaps and tweaks needed to get the filtering working properly.
First, the Core Issue: Missing Filter Logic in Your Adapter
Your CustomStockList has a skeleton getFilter() method, but there’s no actual logic to check if an item matches the search query. Plus, there’s a bug in how you initialize your original and filtered lists (they’re pointing to the same reference, which will cause unexpected behavior).
Step 1: Fix the Adapter Initialization & Filter Logic
Update your CustomStockList with these changes:
private Activity activity; private LayoutInflater inflater; private List<StockData> originalItems; // Store original unfiltered data private List<StockData> filteredItems; private static class ViewHolder { // Add ViewHolder to optimize ListView performance TextView model; TextView stock; } public CustomStockList(Activity activity, List<StockData> items) { this.activity = activity; this.inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); // Create copies of the original list to avoid reference issues this.originalItems = new ArrayList<>(items); this.filteredItems = new ArrayList<>(items); } @Override public int getCount() { return filteredItems.size(); } @Override public Object getItem(int location) { return filteredItems.get(location); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.activity_custom_stock_list, parent, false); holder = new ViewHolder(); holder.model = convertView.findViewById(R.id.model); holder.stock = convertView.findViewById(R.id.stock); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } StockData item = filteredItems.get(position); holder.model.setText(item.getModelno()); holder.stock.setText(item.getStock()); return convertView; } @Override public Filter getFilter() { return new Filter() { @Override protected void publishResults(CharSequence constraint, FilterResults results) { filteredItems = (List<StockData>) results.values; notifyDataSetChanged(); // This updates the ListView with filtered data } @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); List<StockData> tempFilteredList = new ArrayList<>(); if (constraint == null || constraint.length() == 0) { // No filter applied: use original full list tempFilteredList.addAll(originalItems); } else { // Lowercase the query to make filtering case-insensitive String filterQuery = constraint.toString().toLowerCase().trim(); // Check each item against the query for (StockData item : originalItems) { if (item.getModelno().toLowerCase().contains(filterQuery)) { tempFilteredList.add(item); } } } results.values = tempFilteredList; results.count = tempFilteredList.size(); return results; } }; }
Key changes here:
- Created separate
originalItemsandfilteredItemslists (no more shared references) - Added actual filtering logic to match the search query against
modelno(case-insensitive) - Implemented
ViewHolderpattern to optimize ListView scrolling performance - Fixed the filter’s
performFilteringmethod to return the correct filtered results
Step 2: Fix Null Pointer & Adapter Initialization in ListActivity
Your current code tries to call customStockList.getFilter() in onCreate() before the adapter is actually initialized (it’s created later in onPostExecute). Let’s fix that:
First, declare your adapter as a global variable in StockList:
public class StockList extends AppCompatActivity { private ListView lv3; private SearchView sv; private CustomStockList customStockList; private List<StockData> stockList = new ArrayList<>(); // Initialize empty list upfront // ... rest of your code }
Then update the onPostExecute method to properly initialize the adapter:
@Override protected void onPostExecute(Void aVoid) { try { JSONObject object = new JSONObject(result); JSONArray jsonArray = object.getJSONArray("itemstock"); for (int i = 0; i < jsonArray.length(); i++) { JSONObject obj = jsonArray.getJSONObject(i); StockData stockData = new StockData(); stockData.setModelno(obj.getString("modelno")); stockData.setStock(obj.getString("stock")); stockList.add(stockData); } } catch (JSONException e) { Log.e("log_tag", "Error parsing data " + e.toString()); } // Initialize adapter and assign to global variable customStockList = new CustomStockList(StockList.this, stockList); lv3.setAdapter(customStockList); }
Finally, tweak the SearchView listener to avoid null pointers and remove redundant code:
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String s) { return false; } @Override public boolean onQueryTextChange(String s) { if (customStockList != null) { customStockList.getFilter().filter(s); // No need for notifyDataSetChanged here - the filter handles it } return true; // Indicate we've handled the text change event } });
Why This Works
- The adapter now keeps a copy of the original full dataset, so filtering can always reset to the complete list
- The filter logic checks if the item’s
modelnocontains the search query (case-insensitive for better user experience) - We fixed the timing issue where you tried to use the adapter before it was initialized
- The
ViewHolderpattern reduces unnecessary view inflation, making your ListView smoother
Give these changes a try, and your SearchView should start filtering the ListView items as expected!
内容的提问来源于stack exchange,提问作者Arpan Sarkar

