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) }
问题原因
- 未移除数据库监听器:登出后再次登录时,之前添加的
ValueEventListener仍绑定在数据库引用上,新旧监听冲突,导致数据加载逻辑混乱,首条帖子无法正常显示。 - 异步加载顺序问题:
buscarUsuariosSeguidos和mostrarPublicacionesSeguidas是异步执行的,第二次登录时可能帖子查询先完成,但此时关注用户列表还未加载完成,导致部分帖子(含首条)未被筛选加入列表。 - 全局集合未彻底清理:登出后未清空
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
相关产品推荐
相关产品推荐

