notifyDataSetChanged()在Firebase适配器的AutoCompleteTextView中失效问题
问题根源
你的自定义适配器中,clientsListFull是在构造函数里通过new ArrayList<>(clientsList)创建的快照副本。后续MainActivity向clients添加Firebase返回的新数据时,clientsListFull并不会自动同步更新。而AutoCompleteTextView的过滤逻辑完全依赖clientsListFull生成建议列表,所以即便调用notifyDataSetChanged(),Filter使用的还是初始空的clientsListFull,自然显示不出结果。
当你重新创建适配器时,构造函数会用当前已填充数据的clients重新初始化clientsListFull,此时Filter能拿到完整数据,因此功能恢复正常。
解决方案
方案1:给适配器添加全量数据更新方法
在AutoCompleteTxvAdapter中新增方法,用于同步更新clientsListFull并触发过滤:
public void updateFullClientList(List<Client> newClients) { clientsListFull.clear(); clientsListFull.addAll(newClients); // 触发过滤,更新AutoCompleteTextView的显示 getFilter().filter(((AutoCompleteTextView)getContext().findViewById(R.id.autoComplete_txv)).getText()); }
然后在MainActivity的onChildAdded和onChildChanged回调中,替换autoCompleteTxvAdapter.notifyDataSetChanged()为:
autoCompleteTxvAdapter.updateFullClientList(clients);
方案2:修正onChildChanged中的逻辑错误
当前onChildChanged里的代码存在元素插入而非替换的问题,会导致clients和keys列表索引混乱,修正如下:
@Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { Client client = dataSnapshot.getValue(Client.class); String key = dataSnapshot.getKey(); int index = keys.indexOf(key); // 替换原有元素,而非插入 clients.set(index, client); keys.set(index, dataSnapshot.getKey()); autoCompleteTxvAdapter.updateFullClientList(clients); // 生日逻辑... }
方案3:直接复用原列表引用(需注意线程安全)
如果clients列表仅在主线程修改,可以修改适配器构造函数,直接引用原列表而非创建副本:
public AutoCompleteTxvAdapter(@NonNull Context context, @NonNull List<Client> clientsList) { super(context, 0, clientsList); // 直接引用原列表,同步数据源变化 clientsListFull = clientsList; db = new ConnexionDB(context); }
之后在MainActivity中添加数据后,直接调用autoCompleteTxvAdapter.notifyDataSetChanged()即可生效。但需确保所有对clients的修改都在主线程,避免并发修改引发异常。
内容的提问来源于stack exchange,提问作者zineb

