Android Studio中ArrayAdapter的ListView经SearchView过滤后新增元素不显示
根因分析
Android 原生 ArrayAdapter 内部默认维护两套数据集:一套是初始化时传入的原始数据集,另一套是调用 getFilter().filter() 后生成的过滤后展示数据集。你直接修改外部传入的原始 ArrayList 后调用 notifyDataSetChanged() 时,Adapter 会优先基于当前生效的过滤规则匹配原始数据集,若新增元素不匹配当前搜索框关键词,就不会展示;就算匹配,也会因为内部数据集引用不同步导致刷新不生效。
解决方案
可选择以下任意一种方案修复:
- 方案一:使用 ArrayAdapter 自带的操作方法修改数据集,不要直接修改外部 ArrayList
ArrayAdapter提供的add()、remove()等方法会同步修改内部原始数据集,自动触发刷新且自动应用当前过滤规则,适配性最好。
首先修改自定义的aggiungiContatto方法,返回新增的联系人对象:
public Contatto aggiungiContatto(String nome, String cognome, String numeroCell){ Contatto c=new Contatto(nome, cognome, numeroCell); arr.add(c); return c; }
再修改新增元素的逻辑:
public void Aggiungi(View view){ String n,c,t; n = editNome.getText().toString(); c = editCognome.getText().toString(); t = editNumero.getText().toString(); if(!PhoneNumberUtils.isGlobalPhoneNumber("+39" + t) || (t.length() < 8) ){ Toast.makeText(this, "Inserisci un numero internazionale valido.", Toast.LENGTH_SHORT).show(); return; } // 新增元素同时同步到Adapter Contatto newContatto = r.aggiungiContatto(n , c , t); adapter.add(newContatto); // 无需手动调用notifyDataSetChanged,add方法已自动触发刷新 }
- 方案二:添加元素后主动触发一次过滤
如果需要继续自行维护外部 ArrayList,添加元素后主动用当前搜索框的内容重新执行过滤即可:
r.aggiungiContatto(n , c , t); // 用当前搜索框内容重新过滤,同步最新数据集 adapter.getFilter().filter(searchView.getQuery());
- 方案三:添加元素前清空搜索状态
如果业务逻辑允许,添加元素前先清空搜索框,让 Adapter 回到展示全量数据集的状态:
r.aggiungiContatto(n , c , t); // 清空搜索框,第二个参数设为false表示不触发查询提交 searchView.setQuery("", false); adapter.notifyDataSetChanged();
补充建议
如果后续业务逻辑复杂度提升,建议自定义 Adapter 自行维护原始数据集和过滤逻辑,原生 ArrayAdapter 的内部过滤逻辑不透明,容易出现数据集不同步的问题。
内容的提问来源于stack exchange,提问作者Mattia Monari
相关产品推荐
相关产品推荐

