Android根据ArrayList长度切换布局可见性功能失效如何解决?
问题原因与修复方案
核心问题
- Firebase Firestore的
addSnapshotListener是异步操作,你在onCreate中调用监听注册方法后立刻判断列表长度,此时网络请求还未返回,列表为空,所以永远会走显示按钮的逻辑 - 异步回调中把数据添加到列表后,仅通知了适配器刷新,没有重新执行控件显隐逻辑,数据加载完成后UI状态不会同步更新
onCreate中多次调用EventChangeListener()会重复注册监听器,导致后续数据变化时回调多次,列表重复添加数据
修复步骤
1. 抽取UI状态更新公共方法
新增独立的显隐逻辑方法,方便数据变更时重复调用:
// 需先将addMed、addHM、recyclerView、myArrayList设为Activity成员变量 private void updateUIVisibility() { if (myArrayList.isEmpty()) { recyclerView.setVisibility(View.GONE); addMed.setVisibility(View.VISIBLE); addHM.setVisibility(View.VISIBLE); } else { recyclerView.setVisibility(View.VISIBLE); addMed.setVisibility(View.GONE); addHM.setVisibility(View.GONE); } }
2. 精简onCreate逻辑
删除冗余的重复监听调用和初始化时的长度判断:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home_page); // 按钮声明移到成员变量位置,不要做局部变量 addMed = (Button) findViewById(R.id.add_medications_btn); addHM = (Button) findViewById(R.id.add_measurements_btn); rootAuthen = FirebaseAuth.getInstance(); recyclerView = findViewById(R.id.recyclerViewHome); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(this)); myArrayList = new ArrayList<medication_info>(); myAdapter = new myHomeAdpater(home_page.this, myArrayList); recyclerView.setAdapter(myAdapter); // 初始化默认无数据,先更新一次UI updateUIVisibility(); // 仅注册一次监听即可 EventChangeListener(); }
3. 修改异步回调逻辑
每次数据加载完成后触发UI更新,同时优化重复数据问题:
private void EventChangeListener() { FirebaseUser currentFirebaseUser = FirebaseAuth.getInstance().getCurrentUser(); fstore.document("users/"+currentFirebaseUser.getUid()).collection("New Medications") .orderBy("Medication", Query.Direction.ASCENDING).addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots, @Nullable FirebaseFirestoreException e) { if(e != null) { if(progressDialog.isShowing()) progressDialog.dismiss(); Log.e("Firestore error", e.getMessage()); return; } // 先清空旧数据,避免列表重复添加 myArrayList.clear(); for(DocumentChange dc : queryDocumentSnapshots.getDocumentChanges()) { if(dc.getType() == DocumentChange.Type.ADDED) { medication_info m = dc.getDocument().toObject(medication_info.class); m.setId(dc.getDocument().getId()); myArrayList.add(m); } } // 所有数据处理完成后再统一刷新和更新UI myAdapter.notifyDataSetChanged(); updateUIVisibility(); if(progressDialog.isShowing()) { progressDialog.dismiss(); } } }); }
内容的提问来源于stack exchange,提问作者Lance Quinto
相关产品推荐
相关产品推荐

