ListView按bairro字段过滤功能实现问题求助
排查ListView按“bairro”字段过滤异常的问题
你已经折腾ListView的过滤功能好一阵子了,程序没报错但就是不生效,而且列表还得保留只显示状态为PROGRAMADA、日期为当天且属于当前用户的记录,我仔细看了你的代码,发现几个关键问题,咱们一个个来解决:
首先看Activity里的核心问题:每次文本变化都新建Adapter,未复用绑定实例
你在onTextChanged里每次都new了一个OrdemServicoAdapter,然后调用它的filter,但这个新Adapter根本没和你的ListView绑定,过滤后的结果自然不会显示在界面上。正确的做法是把初始设置的Adapter保存为Activity成员变量,直接调用这个实例的filter方法。
修复后的Activity代码片段:
// 把Adapter定义为Activity的成员变量 private OrdemServicoAdapter osAdapter; public void getOSProgramada(){ final ArrayList<OrdemServico> lstOsProgramada = new ArrayList<>(); if(ordem_servicoSerializado.exists()){ try { ArrayList<OrdemServico> lstOS = (ArrayList<OrdemServico>) new SerializarDados().restauraDadosemArquivo(config.sARMAZENAMENTO_ARQUIVO_LOCAL, "ordem_servico"); Usuario usu = (Usuario) new SerializarDados().restauraDadosemArquivo(config.sARMAZENAMENTO_ARQUIVO_LOCAL, "usuario"); for(int i = 0; i < lstOS.size(); i++){ if(lstOS.get(i).getNid_usuario() == usu.getNid_usuario() && lstOS.get(i).getSstatus().equals("PROGRAMADA") && lstOS.get(i).getSdata_programada().equals(""+config.getDataAtual())){ OrdemServico os = new OrdemServico(); // 原有赋值代码保持不变,此处省略 lstOsProgramada.add(os); } } // 初始化Adapter并保存为成员变量,同时绑定到ListView osAdapter = new OrdemServicoAdapter(MenuPrincipalActivity.this, lstOsProgramada); setListAdapter(osAdapter); EditText editText = (EditText) findViewById(R.id.editText1); editText.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence s, int start, int before, int count) { // 直接调用已绑定的Adapter执行过滤 osAdapter.getFilter().filter(s.toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void afterTextChanged(Editable s) {} }); } catch (Exception e) { e.printStackTrace(); } } }
然后是Adapter Filter的三个致命错误
你的Filter逻辑里有几个严重问题,直接导致过滤失效:
- 重复读取本地文件:每次过滤都重新读取全部数据,不仅效率低,还没应用初始过滤规则(PROGRAMADA、当天日期、当前用户),会把不符合要求的记录也纳入过滤范围;
- 添加空对象:循环里创建了空的
OrdemServico os = new OrdemServico();然后添加到列表,过滤后的结果全是空对象,没有有效数据; - 变量名错误:最后给
results赋值时用了lista.size()和lista,但此处应该用你创建的lstOsProgramada,变量名不匹配导致结果为空。
修复后的Adapter Filter代码:
// 给Adapter添加成员变量,保存初始过滤后的原始数据源 private ArrayList<OrdemServico> originalList; private ArrayList<OrdemServico> filteredList; // 在Adapter构造方法里初始化这两个列表 public OrdemServicoAdapter(Context context, ArrayList<OrdemServico> data) { // 原有构造代码保持不变 originalList = new ArrayList<>(data); filteredList = new ArrayList<>(data); } @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence filtro) { FilterResults results = new FilterResults(); filteredList.clear(); if (filtro == null || filtro.length() == 0) { // 无过滤条件时,直接返回原始已筛选列表 filteredList.addAll(originalList); } else { String filterStr = filtro.toString().toUpperCase(); // 仅在已符合初始规则的列表中过滤 for (OrdemServico os : originalList) { String bairro = os.getSbairro().toUpperCase(); if (bairro.contains(filterStr)) { filteredList.add(os); } } } results.count = filteredList.size(); results.values = filteredList; return results; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { // 更新Adapter数据源并通知界面刷新 lista = (ArrayList<OrdemServico>) results.values; notifyDataSetChanged(); } }; }
修复思路总结
- 复用Adapter实例:确保过滤操作在已绑定到ListView的Adapter上执行,避免新建无效实例;
- 保留初始过滤规则:用Adapter保存好已筛选的
PROGRAMADA、当天日期的记录,过滤时仅在这个子集里操作,无需重复读取本地文件; - 修正对象引用:直接添加原始列表中的有效对象,避免创建空对象导致无数据;
- 修复变量名错误:确保
results赋值的是正确的过滤后列表。
这样修改后,按“bairro”字段的过滤功能应该就能正常工作,同时也保留了你原来的固定过滤规则。
内容的提问来源于stack exchange,提问作者Israyane Nayara
相关产品推荐
相关产品推荐

