Android开发:Activity重启时MutableMap被重新初始化,导致滑动隐藏的Firestore通知数据恢复显示
你推测的完全正确——全局的notificationMap会在Activity重新创建(或者应用进程重启)时被重新初始化,导致之前标记的隐藏状态全部丢失。要解决这个问题,核心是把用户隐藏数据的状态持久化保存,这样下次打开Activity时能读取并应用之前的选择。
下面给你两种适合新手的解决方案,从简单到进阶:
方案一:用SharedPreferences轻量存储(推荐新手先试这个)
SharedPreferences是Android自带的轻量级存储工具,专门用来保存小量的键值对数据,比如用户的偏好设置。我们可以用它来记录被用户隐藏的文档ID列表。
步骤1:初始化SharedPreferences
在你的NotificationDashboard类里添加SharedPreferences实例,并在onCreate中初始化:
private lateinit var sharedPrefs: SharedPreferences override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityNotificationDashboardBinding.inflate(layoutInflater) setContentView(binding.root) // 初始化SharedPreferences,命名为NotificationPrefs sharedPrefs = getSharedPreferences("NotificationPrefs", MODE_PRIVATE) // 其他原有代码... }
步骤2:修改滑动隐藏/撤销的逻辑
更新ItemTouchHelper的onSwiped方法,把隐藏的文档ID存入SharedPreferences,撤销时移除:
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { val position = viewHolder.adapterPosition val deletedNotification = notificationArray[position] val documentID = deletedNotification.docID // 保存隐藏状态到SharedPreferences val hiddenIds = sharedPrefs.getStringSet("hidden_notifications", mutableSetOf())?.toMutableSet() hiddenIds?.add(documentID) sharedPrefs.edit().putStringSet("hidden_notifications", hiddenIds).apply() // 更新列表并通知适配器 notificationArray.removeAt(position) myRecyclerAdapter.notifyItemRemoved(position) Snackbar.make(myRecylerView, deletedNotification.title.toString(), Snackbar.LENGTH_SHORT).setAction("Undo") { // 撤销时移除隐藏状态 val hiddenIdsUndo = sharedPrefs.getStringSet("hidden_notifications", mutableSetOf())?.toMutableSet() hiddenIdsUndo?.remove(documentID) sharedPrefs.edit().putStringSet("hidden_notifications", hiddenIdsUndo).apply() // 恢复数据到列表 notificationArray.add(position, deletedNotification) myRecyclerAdapter.notifyItemInserted(position) }.show() }
步骤3:加载Firestore数据时过滤隐藏项
修改searchFireStore方法,读取SharedPreferences里的隐藏ID列表,只加载未被隐藏的数据:
private fun searchFireStore(){ val db = FirebaseFirestore.getInstance() // 获取已隐藏的文档ID集合 val hiddenIds = sharedPrefs.getStringSet("hidden_notifications", mutableSetOf()) ?: mutableSetOf() db.collection(collID).get() .addOnCompleteListener { task -> if (task.isSuccessful) { notificationArray.clear() // 先清空旧数据 for (document in task.result!!) { val docID = document.id // 只添加未被隐藏的数据 if (!hiddenIds.contains(docID)) { val notification = NotificationClass( document.data["Title"] as String?, document.data["Notification"] as String?, true, docID ) notificationArray.add(notification) } } // 更新RecyclerView适配器 myRecylerView.layoutManager = LinearLayoutManager(this) myRecyclerAdapter = MyRecyclerAdapter(notificationArray) myRecylerView.adapter = myRecyclerAdapter myRecyclerAdapter.notifyDataSetChanged() Log.d("FOR", "Success of FOR LOOP") } } }
额外优化:去掉全局的notificationMap
现在状态靠SharedPreferences维护,你可以直接删除全局的notificationMap变量,简化代码结构。
方案二:用Firestore同步隐藏状态(适合多设备同步场景)
如果你希望用户在不同设备上打开应用时,隐藏状态能同步,可以把隐藏的文档ID存在用户的Firestore文档里。
步骤1:更新用户文档存储隐藏ID
在滑动隐藏时,把文档ID添加到用户文档的hiddenNotifications数组中:
// 滑动隐藏时 db.collection("users").document(userEmail) .update("hiddenNotifications", FieldValue.arrayUnion(documentID)) .addOnSuccessListener { // 处理成功逻辑 } // 撤销时,从数组中移除 db.collection("users").document(userEmail) .update("hiddenNotifications", FieldValue.arrayRemove(documentID)) .addOnSuccessListener { // 处理成功逻辑 }
步骤2:加载数据时先获取用户的隐藏列表
在searchFireStore之前,先获取用户的hiddenNotifications列表,再过滤数据:
// 在获取collID之后,先获取用户的隐藏列表 db.collection("users").document(userEmail).get() .addOnSuccessListener { document -> val hiddenIds = document.get("hiddenNotifications") as? List<String> ?: emptyList() // 调用searchFireStore时传入hiddenIds searchFireStore(hiddenIds) } // 修改searchFireStore方法接收hiddenIds参数 private fun searchFireStore(hiddenIds: List<String>){ val db = FirebaseFirestore.getInstance() db.collection(collID).get() .addOnCompleteListener { task -> if (task.isSuccessful) { notificationArray.clear() for (document in task.result!!) { val docID = document.id if (!hiddenIds.contains(docID)) { val notification = NotificationClass( document.data["Title"] as String?, document.data["Notification"] as String?, true, docID ) notificationArray.add(notification) } } // 更新适配器... } } }
这个方案需要处理异步请求的顺序,但能实现多设备同步,适合有账号系统的应用。
两种方案都能解决你的问题,推荐先从SharedPreferences方案入手,实现起来简单快速,适合新手理解。
内容的提问来源于stack exchange,提问作者Daksh

