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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 14:42:37