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

Firestore查询执行两次致Activity重复创建问题求助

解决Firestore监听器回调两次导致Activity重复创建的问题

问题原因

你碰到的这个情况是Firestore addSnapshotListener的默认机制导致的:这个实时监听器会先触发一次本地缓存的查询结果(如果之前有过相同查询的缓存数据),然后再触发一次从服务器拉取的最新数据快照。所以哪怕你的firebase_dynamicview()只调用一次,onEvent回调也会执行两次,日志2222222222自然打印两次,最终重复调用userprofile()导致Activity被多次创建。

解决方案

根据你的业务需求,分两种场景给出解决办法:

场景1:不需要实时监听数据(仅一次性加载)

如果你的业务只需要一次性获取员工数据,不需要实时同步更新,直接把addSnapshotListener换成一次性查询的get()方法即可,它只会执行一次回调:

private void firebase_dynamicview() { 
    shared_menueditor.clear().commit();
    shared_menueditor.putString("success", "failure");
    shared_menueditor.apply();
    Log.d("gettingcall","11111111111 ");
    db = FirebaseFirestore.getInstance();
    Query query = db.collection("employees");
    
    // 替换成一次性get查询
    query.whereEqualTo("UID", sharedPref.getString("userId",null))
        .get()
        .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()) {
                    QuerySnapshot documentSnapshots = task.getResult();
                    if (documentSnapshots.isEmpty()){ 
                        closeSplash(); 
                        return;
                    }
                    Log.d("gettingcall","2222222222 ");
                    // 以下是你原来的解析逻辑
                    for (DocumentChange documentChange : documentSnapshots.getDocumentChanges()) {
                        Map<String, Object> forms =null;
                        if (documentChange.getDocument().getData().get("mobileMenu") != null) {
                            try {
                                forms= (Map<String, Object>)documentChange.getDocument().getData().get("mobileMenu");
                            } catch (Exception e1) {
                                Log.e("Execeptionmenus","** "+e1.toString());
                                e1.printStackTrace();
                            }
                        }
                        if (forms!= null) {
                            // ... 原来的遍历解析逻辑
                        }
                    }
                    shared_menueditor.apply();
                    editor.apply();
                    Log.d("calllliiiiiiing******","spalsh");
                    userprofile();
                } else {
                    // 处理查询失败的情况
                    Log.e("FirestoreError", task.getException().getMessage());
                    closeSplash();
                }
            }
        });
} 

场景2:需要实时监听数据,但避免重复启动Activity

如果业务需要实时同步员工数据的变化,但不想重复执行userprofile()启动Activity,可以通过以下两种方式处理:

  • 方式1:跳过本地缓存的初始触发
    判断快照是否来自本地缓存,只处理服务器返回的最新数据:
// 在你的addSnapshotListener回调里添加判断
@Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
    if (e != null) { 
        Log.e("FirestoreError", e.getMessage());
        return;
    }
    // 跳过本地缓存的快照,只处理服务器返回的数据
    if (documentSnapshots.getMetadata().isFromCache()) {
        return;
    }
    // 以下是你原来的逻辑
    if (documentSnapshots.isEmpty()){ closeSplash(); }
    Log.d("gettingcall","2222222222 ");
    // ... 解析数据
    shared_menueditor.apply();
    editor.apply();
    userprofile();
}
  • 方式2:用标记变量控制只执行一次初始化
    在类中定义一个成员变量标记是否已经启动过Activity,确保userprofile()只执行一次:
// 在你的Activity类中添加成员变量
private boolean isProfileInitiated = false;

// 然后在回调中判断
@Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
    if (e != null) { 
        Log.e("FirestoreError", e.getMessage());
        return;
    }
    if (documentSnapshots.isEmpty()){ closeSplash(); }
    Log.d("gettingcall","2222222222 ");
    // ... 先完成所有数据解析和SharedPreferences存储逻辑
    shared_menueditor.apply();
    editor.apply();
    // 只有第一次才启动Activity
    if (!isProfileInitiated) {
        userprofile();
        isProfileInitiated = true;
    }
}

额外优化建议

你的代码中多次调用shared_menueditor.apply()和commit(),其实只需要在所有putString()操作完成后,调用一次apply()(异步,推荐)或者commit()(同步)即可,这样能减少不必要的IO操作,提升性能。

内容的提问来源于stack exchange,提问作者Gowthaman M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:26:36