使用自定义Adapter时SearchView仅显示ListView同一条记录,ArrayAdapter正常
Hey there, let's sort out why your custom EMP_LEAVE_ADAPTER is showing duplicate records in the SearchView while the default ArrayAdapter works perfectly!
The Root Cause
The issue comes down to how your custom adapter interacts with ArrayAdapter's built-in filtering system. When you use a SearchView, ArrayAdapter relies on its internal dataset to handle filtering. But your adapter was maintaining its own itemname array that didn't sync with the filtered dataset managed by the parent class. This mismatch meant the adapter kept pulling data from your static array instead of the updated filtered list, leading to repeated entries.
Solution 1: Use the Parent Class's Dataset (Simplest Fix)
Remove your custom itemname array and use the parent ArrayAdapter's built-in methods to access data. This ensures you're always working with the correct filtered dataset.
Here's the revised adapter code:
import com.example.mis_internee.atendence_app_android.R; import android.app.Activity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; public class EMP_LEAVE_ADAPTER extends ArrayAdapter<String> { private final Activity context; public EMP_LEAVE_ADAPTER(Activity context, String[] itemname) { super(context, R.layout.mylist, itemname); this.context = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { // Reuse existing views to boost performance View rowView = convertView; if (rowView == null) { LayoutInflater inflater = context.getLayoutInflater(); rowView = inflater.inflate(R.layout.emp_leave_adpater_layout, parent, false); } TextView txtTitle = rowView.findViewById(R.id.item); ImageView image = rowView.findViewById(R.id.icon); // Use getItem() from the parent class to get filtered data txtTitle.setText(getItem(position)); return rowView; } }
Key changes:
- Removed the custom
itemnamearray - Added view reuse (avoids inflating new views every time, improves performance)
- Used
getItem(position)to fetch data directly from the parent's filtered dataset
Solution 2: Custom Filter Logic (If You Need Full Control)
If you need to maintain your own dataset for specific logic, you'll have to override the getFilter() method to handle filtering correctly. Here's how:
import com.example.mis_internee.atendence_app_android.R; import android.app.Activity; import android.widget.ArrayAdapter; import android.widget.Filter; import android.widget.Filterable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class EMP_LEAVE_ADAPTER extends ArrayAdapter<String> implements Filterable { private final Activity context; private final String[] originalItemNames; private List<String> filteredItemNames; public EMP_LEAVE_ADAPTER(Activity context, String[] itemname) { super(context, R.layout.mylist, itemname); this.context = context; this.originalItemNames = itemname.clone(); this.filteredItemNames = new ArrayList<>(Arrays.asList(itemname)); } @Override public View getView(int position, View convertView, ViewGroup parent) { View rowView = convertView; if (rowView == null) { LayoutInflater inflater = context.getLayoutInflater(); rowView = inflater.inflate(R.layout.emp_leave_adpater_layout, parent, false); } TextView txtTitle = rowView.findViewById(R.id.item); ImageView image = rowView.findViewById(R.id.icon); txtTitle.setText(filteredItemNames.get(position)); return rowView; } @Override public int getCount() { return filteredItemNames.size(); } @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); List<String> filteredList = new ArrayList<>(); if (constraint == null || constraint.length() == 0) { // No filter applied: use original data filteredList.addAll(Arrays.asList(originalItemNames)); } else { String filterPattern = constraint.toString().toLowerCase().trim(); // Match items against the filter for (String item : originalItemNames) { if (item.toLowerCase().contains(filterPattern)) { filteredList.add(item); } } } results.values = filteredList; results.count = filteredList.size(); return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { filteredItemNames = (List<String>) results.values; notifyDataSetChanged(); } }; } }
This version maintains a separate original dataset and filtered list, with explicit filter logic to update the list and notify the adapter of changes.
内容的提问来源于stack exchange,提问作者Kamran Ijaz

