Firestore数据更新时RecyclerView崩溃问题求助
我通过Firebase Firestore集合展示数据,应用原本运行正常,但当通过外部设备(带传感器的Arduino连接电脑,通过Python脚本将串口数据转为JSON后更新Firestore集合,后端功能完全正常)更新集合数据时,安卓端无法自动刷新RecyclerView显示最新数据。
已经在论坛搜索解决方案,推测问题出在Adapter、RecyclerView和notifyDataSetChanged()上,但现有方案均未生效,可能是我不会在项目中正确实现。
以下是我的代码:
模型类
public class Monitor { String alias, placa, temp, acid; public Monitor(){} public Monitor(String alias, String placa, String temp, String acid) { this.alias = alias; this.placa = placa; this.temp = temp; this.acid = acid; } public String getAlias() { return alias; } public void setAlias(String alias) { this.alias = alias; } public String getPlaca() { return placa; } public void setPlaca(String placa) { this.placa = placa; } public String getTemp() { return temp; } public void setTemp(String temp) { this.temp = temp; } public String getAcid() { return acid; } public void setAcid(String acid) { this.acid = acid; } }
Adapter类
public class MonitorAdapter extends FirestoreRecyclerAdapter<Monitor, MonitorAdapter.ViewHolder> { private FirebaseFirestore mFirestore = FirebaseFirestore.getInstance(); Activity activity; public MonitorAdapter(@NonNull FirestoreRecyclerOptions<Monitor> options, Activity activity) { super(options); this.activity = activity; } @Override protected void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull Monitor model) { DocumentSnapshot documentSnapshot = getSnapshots().getSnapshot(holder.getAbsoluteAdapterPosition()); final String id = documentSnapshot.getId(); holder.alias.setText(model.getAlias()); holder.temp.setText(model.getTemp()); holder.acid.setText(model.getAcid()); holder.btn_edit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent i = new Intent(activity, VincularPlaca.class); i.putExtra("id_placa",id); activity.startActivity(i); } }); } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_monitor_single,parent,false); return new ViewHolder(view); } public class ViewHolder extends RecyclerView.ViewHolder { TextView alias, temp, acid; Button btn_edit; public ViewHolder(@NonNull View itemView) { super(itemView); alias = itemView.findViewById(R.id.alias); temp = itemView.findViewById(R.id.temp); acid = itemView.findViewById(R.id.acid); btn_edit = itemView.findViewById(R.id.btn_edit); } } }
MainActivity类
public class MainActivity extends AppCompatActivity { Button btn_add, btn_exit; RecyclerView mRecycler; MonitorAdapter mAdapter; FirebaseFirestore mFirestore; FirebaseAuth mAuth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mFirestore = FirebaseFirestore.getInstance(); mRecycler = findViewById(R.id.recyclerViewSingle); mRecycler.setLayoutManager(new LinearLayoutManager(this)); Query query = mFirestore.collection("dispositivos"); FirestoreRecyclerOptions<Monitor> firestoreRecyclerOptions = new FirestoreRecyclerOptions.Builder<Monitor>().setQuery(query,Monitor.class).build(); mAdapter = new MonitorAdapter(firestoreRecyclerOptions, this); mAdapter.notifyDataSetChanged(); mRecycler.setAdapter(mAdapter); btn_add = findViewById(R.id.btn_add); btn_exit = findViewById(R.id.btn_close); btn_add.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startActivity(new Intent(MainActivity.this,VincularPlaca.class)); } }); btn_exit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startActivity(new Intent(MainActivity.this,LoginActivity.class)); mAuth.signOut(); } }); } @Override protected void onStart() { super.onStart(); mAdapter.startListening(); } @Override protected void onStop() { super.onStop(); mAdapter.stopListening(); } }
你使用的FirestoreRecyclerAdapter本身具备自动监听Firestore数据变化并刷新UI的能力,未生效的原因可从以下几点排查修复:
校验字段匹配一致性
Firestore自动映射数据时严格区分字段大小写,检查Python脚本写入Firestore的字段名是否和Monitor类的alias、placa、temp、acid完全一致,比如Python中若写Temperature而非temp,会导致数据映射失败,UI无法更新。移除无效的手动刷新调用
onCreate中调用mAdapter.notifyDataSetChanged()毫无意义——此时适配器尚未开始监听数据,且FirestoreRecyclerAdapter不需要手动调用该方法,它会自动处理数据更新。添加数据变化回调确认
若自动刷新仍未触发,可在Adapter中重写onDataChanged()方法,确保感知到数据变化:
@Override public void onDataChanged() { super.onDataChanged(); // 可添加日志确认回调是否触发,比如Log.d("Adapter", "数据已更新"); }
该方法会在Firestore数据发生增删改查时自动调用,保障适配器同步数据变化。
- 优化Query稳定性
当前的Query仅指定集合,无排序或过滤条件,数据量较大时可能导致监听延迟。建议添加排序条件,例如:
Query query = mFirestore.collection("dispositivos").orderBy("placa");
排序后的Query能让Firestore监听更稳定,数据更新后更快触发UI刷新。
- 修复空指针异常
MainActivity中mAuth未初始化,btn_exit点击事件里的mAuth.signOut()会引发空指针异常,影响页面运行逻辑,需补上初始化:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mFirestore = FirebaseFirestore.getInstance(); mAuth = FirebaseAuth.getInstance(); // 补上该行初始化代码 // 其他原有代码... }
按以上步骤调整后,外部设备更新Firestore数据时,安卓端RecyclerView即可自动刷新显示最新内容。
内容的提问来源于stack exchange,提问作者RodrigoMardones

