Android端Firestore分类数据登出丢失问题求助
问题分析与解决方案
核心问题原因
- 登出后重新登录时,未从Firestore重新加载当前用户的分类数据,导致界面为空
- SharedPreferences仅实现了存储逻辑,但未在登录后执行读取操作,且它是本地存储,无法替代Firestore的云端持久化作用
- 代码中
TaskGroup的groupId硬编码为"groupId",无法与Firestore生成的文档ID对应,可能破坏数据关联逻辑 - 添加分类时新建
CategoriesAdapter实例,而非复用主活动中已绑定的适配器,可能导致界面更新失效
分步解决方案
1. 修复Firestore数据加载逻辑(关键)
在主活动的onStart方法中添加数据查询逻辑,确保登录后自动拉取当前用户的分类:
@Override protected void onStart() { super.onStart(); FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser(); if (currentUser != null) { loadCategoriesFromFirestore(currentUser.getUid()); } } private void loadCategoriesFromFirestore(String userId) { FirebaseFirestore firestore = FirebaseFirestore.getInstance(); firestore.collection("categories") .whereEqualTo("userId", userId) .addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException error) { if (error != null) { Toast.makeText(MainActivity.this, "加载分类失败: " + error.getMessage(), Toast.LENGTH_SHORT).show(); return; } categoriesList.clear(); for (QueryDocumentSnapshot doc : value) { TaskGroup taskGroup = doc.toObject(TaskGroup.class); taskGroup.setGroupId(doc.getId()); categoriesList.add(taskGroup); } if (categoriesAdapter != null) { categoriesAdapter.notifyDataSetChanged(); } } }); }
2. 修正Firestore分类存储的groupId
添加分类到Firestore时,用生成的文档ID更新TaskGroup的groupId,确保数据关联正确:
firestore.collection("categories").add(newGroup) .addOnSuccessListener(documentReference -> { Toast.makeText(MainActivity.this, "Category saved in Firestore", Toast.LENGTH_SHORT).show(); // 更新TaskGroup的groupId为Firestore文档ID newGroup.setGroupId(documentReference.getId()); // 同步更新本地列表 int index = categoriesList.indexOf(newGroup); if (index != -1) { categoriesList.set(index, newGroup); categoriesAdapter.notifyItemChanged(index); } saveCategoryToSharedPreferences(categoryName); })
3. 优化SharedPreferences读取逻辑(可选)
若需本地缓存,在主活动启动时读取SharedPreferences的分类并同步到界面(核心数据仍以Firestore为准):
private void loadCategoriesFromSharedPreferences() { SharedPreferences sharedPreferences = getSharedPreferences("categories", MODE_PRIVATE); Set<String> categoriesSet = sharedPreferences.getStringSet("categories", new HashSet<>()); for (String name : categoriesSet) { boolean exists = false; for (TaskGroup group : categoriesList) { if (group.getCategoryName().equals(name)) { exists = true; break; } } if (!exists) { TaskGroup tempGroup = new TaskGroup(name, "", name, new ArrayList<>(), Collections.singletonList(R.drawable.ic_lists), 0, true, FirebaseAuth.getInstance().getCurrentUser().getUid(), true); categoriesList.add(tempGroup); } } if (categoriesAdapter != null) { categoriesAdapter.notifyDataSetChanged(); } }
4. 复用适配器实例
在主活动中全局声明适配器,避免重复创建:
// 主活动类成员变量 private CategoriesAdapter categoriesAdapter; // 在onCreate中初始化 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); categoriesList = new ArrayList<>(); categoriesAdapter = new CategoriesAdapter(categoriesList, this); // 绑定RecyclerView RecyclerView recyclerView = findViewById(R.id.categories_recycler); recyclerView.setAdapter(categoriesAdapter); // ...其他初始化逻辑 }
关键注意事项
- 始终以Firestore云端数据为唯一可信源,SharedPreferences仅作为本地缓存辅助使用
- 配置Firestore规则,确保用户仅能读写自己的分类数据:
match /categories/{doc} { allow read, write: if request.auth != null && request.auth.uid == resource.data.userId; } - 登出时清空本地
categoriesList和SharedPreferences数据,避免数据混淆
内容的提问来源于stack exchange,提问作者faith milly
相关产品推荐
相关产品推荐

