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

如何在Fragment中实现用户登录状态监听与UI更新?

Fixing Fragment UI Update Issues with Firebase Auth & LiveData

Let's break down why your code works in an Activity but not a Fragment, and fix it step by step:

Key Differences Between Activity and Fragment Lifecycles

Fragments have a separate view lifecycle from the Fragment itself. Using this (the Fragment instance) for LiveData observation can lead to observers outliving the view, causing no updates or memory leaks. Additionally, Firebase listeners need proper cleanup to avoid redundant calls and leaks.

Step-by-Step Fixes

1. Declare Member Variables in Your Fragment

First, add these variables to your Fragment class to manage Firebase listeners and LiveData:

private lateinit var database: DatabaseReference
private lateinit var mAuth: FirebaseAuth
private val mutableName = MutableLiveData<String>("Guest")
private val mutableSurname = MutableLiveData<String>("")
private var userDbListener: ValueEventListener? = null
private var authStateListener: FirebaseAuth.AuthStateListener? = null

2. Initialize Views and Set Up Listeners

Call your updateUI function in onViewCreated (after the view is inflated), and add an AuthStateListener to detect sign-in/out changes automatically:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    
    // Initialize your TextViews here
    val userName = view.findViewById<TextView>(R.id.user_name)
    val userSurname = view.findViewById<TextView>(R.id.user_surname)
    
    mAuth = FirebaseAuth.getInstance()
    database = FirebaseDatabase.getInstance().reference
    
    // Listen for auth state changes to update UI automatically
    authStateListener = FirebaseAuth.AuthStateListener { auth ->
        updateUI(userName, userSurname)
    }
    mAuth.addAuthStateListener(authStateListener!!)
}

3. Rewrite the updateUI Function

Update the function to use viewLifecycleOwner for LiveData observation and manage the Firebase listener properly:

private fun updateUI(userName: TextView, userSurname: TextView) {
    println("Updating UI")
    
    // Remove existing database listener to avoid duplicate calls
    userDbListener?.let {
        mAuth.currentUser?.uid?.let { uid ->
            database.child("users").child(uid).removeEventListener(it)
        }
    }

    if (mAuth.currentUser != null) {
        val userId = mAuth.currentUser!!.uid
        userDbListener = object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                if (snapshot.exists()) {
                    println("User found")
                    mutableName.postValue(snapshot.child("name").value.toString())
                    mutableSurname.postValue(snapshot.child("surname").value.toString())
                } else {
                    println("User not found")
                    resetToGuest()
                }
            }

            override fun onCancelled(error: DatabaseError) {
                println(error.message)
                resetToGuest()
            }
        }
        database.child("users").child(userId).addValueEventListener(userDbListener!!)
    } else {
        println("User not signed in")
        resetToGuest()
    }

    // Observe LiveData with viewLifecycleOwner to tie to the view's lifecycle
    mutableName.observe(viewLifecycleOwner) { name ->
        userName.text = name
    }
    
    mutableSurname.observe(viewLifecycleOwner) { surname ->
        userSurname.text = surname
    }
}

private fun resetToGuest() {
    mutableName.postValue("Guest")
    mutableSurname.postValue("")
}

4. Clean Up Listeners to Prevent Leaks

Remove all listeners when the Fragment's view is destroyed:

override fun onDestroyView() {
    super.onDestroyView()
    
    // Remove Firebase auth listener
    authStateListener?.let {
        mAuth.removeAuthStateListener(it)
    }
    
    // Remove Firebase database listener
    userDbListener?.let {
        mAuth.currentUser?.uid?.let { uid ->
            database.child("users").child(uid).removeEventListener(it)
        }
    }
    
    // Nullify listeners to avoid memory leaks
    authStateListener = null
    userDbListener = null
}

Why This Works

  • viewLifecycleOwner: Ensures LiveData observers only update the UI when the Fragment's view is active, preventing crashes or missed updates after view recreation (e.g., screen rotation).
  • Listener Cleanup: Removing Firebase listeners in onDestroyView stops unnecessary database reads and prevents memory leaks.
  • AuthStateListener: Automatically triggers updateUI whenever the user signs in or out, so you don't have to manually call it after auth actions.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:13:53