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

Firebase实时数据库登出再登录后RecyclerView首条数据不显示

问题描述

开发的类社交APP需展示已认证用户关注的所有用户帖子。首次登录时RecyclerView显示正常,但用户执行登出操作后再次登录,首条帖子无法显示,重启APP则恢复正常,怀疑问题出在RecyclerView但不确定。

数据库结构截图

数据库结构

相关代码

数据查询代码

private fun buscarUsuariosSeguidos(usuarioUid:String){
    //BUSCAMOS EN LA TABLA SEGUIR CADA ENTRADA DONDE APAREZCA COMO SEGUIDOR EL USUARIO AUTENTIFICADO
    val seguidoresRef= referenciaBD.child("Seguir").child(usuarioUid).child("Siguiendo")
    // LIMPIAMOS LAS PUBLICACIONES SEGUIDAS
    usuariosSeguidosUid?.clear()
    //CARGAMOS LAS PUBLICACIONES EN EL RECYCLERVIEW DATACHANGE SE ENCARGA DE CARGAR LOS DATOS
    seguidoresRef.addValueEventListener(object :ValueEventListener{
        override fun onDataChange(snapshot: DataSnapshot) {
            if (snapshot.exists()){
                for (snap in snapshot.children)
                    //RECUPERAMOS LA CLAVE DE CADA CHILDREN QUE REALMENTE ES EL UID DEL USUARIO
                    snap.key?.let { (usuariosSeguidosUid as ArrayList<String>).add(it) }
            }
        }
        override fun onCancelled(error: DatabaseError) {
        }
    })
}
//ESTA FUNCION BUSCA LAS PUBLICACIONES DE TODOS LOS USUARIOS QUE SIGUE EL USUARIO AUTENTIFICADO
private fun mostrarPublicacionesSeguidas() {
    //CREAMOS LA QUERY DE BUSQUEDA QUE APUNTA A LA TABLA PUBLICACIONES
    val publicacionRef = referenciaBD.child("Publicaciones")
    //listaPublicaciones?.clear()
    publicacionRef.addValueEventListener(object : ValueEventListener {
        //CARGAMOS TODOS LOS DATOS DE LA TABLA POSTS EN EL RECYCLERVIEW DATACHANGE SE ENCARGA DE CARGAR LOS DATOS
        override fun onDataChange(snapshot: DataSnapshot) {
            //LIMPIAMOS LA LISTA DE PUBLICACIONES
            listaPublicaciones?.clear()
            for (snapshot in snapshot.children) {
                // SE VA RECUPÈRANDO CADA PUBLICACION
                val publicacion = snapshot.getValue(Publicacion::class.java)
                // Y SE RECORRE EL ARRAY CON LOS UID DE LOS USUARIOS SEGUIDOS PARA VER SI SE DEBE MOSTRAR
                for (usuarioUid in usuariosSeguidosUid as ArrayList<String>)
                    // EN CASO DE QUE SE ENCUENTRE CONICIDENCIA SE AÑADE LA PUBLICACION A SU LISTA
                    if (usuarioUid == publicacion!!.nombreUsuario ){
                        listaPublicaciones?.add(publicacion!!)
                    }
            }
            //invertimos la lista para que los ultimos posts esten os primero
            listaPublicaciones!!.reverse()
            //SE ACTUALIZA EL LISTADO DE PUBLICACIONES MOSTRADOR EN EL ADAPTADOR
            publicacionAdaptador?.notifyDataSetChanged()
        }
        override fun onCancelled(error: DatabaseError) {
            //VER QUE HACE
        }
    })
}

登出函数

private fun desconectarUsuario(){
    FirebaseAuth.getInstance().signOut()
    val intent = Intent(context,IdentificarseActivity::class.java)
    startActivity(intent)
}

问题原因

  1. 未移除数据库监听器:登出后再次登录时,之前添加的ValueEventListener仍绑定在数据库引用上,新旧监听冲突,导致数据加载逻辑混乱,首条帖子无法正常显示。
  2. 异步加载顺序问题:buscarUsuariosSeguidos和mostrarPublicacionesSeguidas是异步执行的,第二次登录时可能帖子查询先完成,但此时关注用户列表还未加载完成,导致部分帖子(含首条)未被筛选加入列表。
  3. 全局集合未彻底清理:登出后未清空usuariosSeguidosUid和listaPublicaciones,残留旧用户数据与新用户数据混合,引发显示异常。

解决方法

1. 管理数据库监听器,避免内存泄漏与冲突

定义全局变量存储监听器,在登出或页面销毁时移除,同时保证每次登录只绑定新监听:

private var seguidoresListener: ValueEventListener? = null
private var publicacionesListener: ValueEventListener? = null

private fun buscarUsuariosSeguidos(usuarioUid:String){
    val seguidoresRef= referenciaBD.child("Seguir").child(usuarioUid).child("Siguiendo")
    usuariosSeguidosUid?.clear()
    
    // 先移除旧监听
    seguidoresListener?.let { seguidoresRef.removeEventListener(it) }
    
    seguidoresListener = object :ValueEventListener{
        override fun onDataChange(snapshot: DataSnapshot) {
            if (snapshot.exists()){
                usuariosSeguidosUid?.clear()
                for (snap in snapshot.children)
                    snap.key?.let { (usuariosSeguidosUid as ArrayList<String>).add(it) }
                // 加载完关注用户后再查询帖子
                mostrarPublicacionesSeguidas()
            } else {
                listaPublicaciones?.clear()
                publicacionAdaptador?.notifyDataSetChanged()
            }
        }
        override fun onCancelled(error: DatabaseError) {}
    }
    seguidoresRef.addValueEventListener(seguidoresListener!!)
}

private fun mostrarPublicacionesSeguidas() {
    val publicacionRef = referenciaBD.child("Publicaciones")
    
    // 先移除旧监听
    publicacionesListener?.let { publicacionRef.removeEventListener(it) }
    
    publicacionesListener = object : ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            listaPublicaciones?.clear()
            for (snap in snapshot.children) {
                val publicacion = snap.getValue(Publicacion::class.java)
                publicacion?.let { pub ->
                    if ((usuariosSeguidosUid as ArrayList<String>).contains(pub.nombreUsuario)) {
                        listaPublicaciones?.add(pub)
                    }
                }
            }
            listaPublicaciones?.reverse()
            publicacionAdaptador?.notifyDataSetChanged()
        }
        override fun onCancelled(error: DatabaseError) {}
    }
    publicacionRef.addValueEventListener(publicacionesListener!!)
}

// 页面销毁时移除监听器
override fun onDestroy() {
    super.onDestroy()
    val currentUid = FirebaseAuth.getInstance().currentUser?.uid ?: ""
    val seguidoresRef= referenciaBD.child("Seguir").child(currentUid).child("Siguiendo")
    seguidoresListener?.let { seguidoresRef.removeEventListener(it) }
    
    val publicacionRef = referenciaBD.child("Publicaciones")
    publicacionesListener?.let { publicacionRef.removeEventListener(it) }
}

2. 保证数据加载顺序

在buscarUsuariosSeguidos的onDataChange回调中调用mostrarPublicacionesSeguidas,确保只有关注用户列表加载完成后,才进行帖子筛选,避免空数据导致的筛选异常。

3. 登出时彻底清理数据

在登出函数中清空全局集合、移除监听器并结束当前页面:

private fun desconectarUsuario(){
    FirebaseAuth.getInstance().signOut()
    // 清空数据集合
    usuariosSeguidosUid?.clear()
    listaPublicaciones?.clear()
    publicacionAdaptador?.notifyDataSetChanged()
    
    // 移除监听器
    val currentUid = FirebaseAuth.getInstance().currentUser?.uid ?: ""
    val seguidoresRef= referenciaBD.child("Seguir").child(currentUid).child("Siguiendo")
    seguidoresListener?.let { seguidoresRef.removeEventListener(it) }
    
    val publicacionRef = referenciaBD.child("Publicaciones")
    publicacionesListener?.let { publicacionRef.removeEventListener(it) }
    
    val intent = Intent(context,IdentificarseActivity::class.java)
    startActivity(intent)
    finish() // 结束当前页面,避免返回后数据异常
}

4. 优化帖子筛选逻辑

替换嵌套循环为contains方法,同时避免非空断言的不安全使用:

publicacion?.let { pub ->
    if ((usuariosSeguidosUid as ArrayList<String>).contains(pub.nombreUsuario)) {
        listaPublicaciones?.add(pub)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 22:35:37