You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的能力,未生效的原因可从以下几点排查修复:

  1. 校验字段匹配一致性
    Firestore自动映射数据时严格区分字段大小写,检查Python脚本写入Firestore的字段名是否和Monitor类的alias、placa、temp、acid完全一致,比如Python中若写Temperature而非temp,会导致数据映射失败,UI无法更新。

  2. 移除无效的手动刷新调用
    onCreate中调用mAdapter.notifyDataSetChanged()毫无意义——此时适配器尚未开始监听数据,且FirestoreRecyclerAdapter不需要手动调用该方法,它会自动处理数据更新。

  3. 添加数据变化回调确认
    若自动刷新仍未触发,可在Adapter中重写onDataChanged()方法,确保感知到数据变化:

@Override
public void onDataChanged() {
    super.onDataChanged();
    // 可添加日志确认回调是否触发,比如Log.d("Adapter", "数据已更新");
}

该方法会在Firestore数据发生增删改查时自动调用,保障适配器同步数据变化。

  1. 优化Query稳定性
    当前的Query仅指定集合,无排序或过滤条件,数据量较大时可能导致监听延迟。建议添加排序条件,例如:
Query query = mFirestore.collection("dispositivos").orderBy("placa");

排序后的Query能让Firestore监听更稳定,数据更新后更快触发UI刷新。

  1. 修复空指针异常
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 04:20:20