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

Jetpack Compose中Firebase头像更新后UI未即时刷新问题求助

问题分析

你的问题核心有两点:

  1. updateUserProfile函数里的CompletableDeferred被两次调用complete,导致函数提前返回,此时用户资料还没完成更新,getSignedInUser()拿到的仍是旧头像URL。
  2. Firebase Auth的currentUser存在本地缓存,更新后不会立即同步,直接调用getSignedInUser()大概率取到旧数据。
解决方案

1. 修复updateUserProfile函数逻辑

确保图片上传完成+用户资料更新完成两个操作都成功后再返回结果,同时直接返回最新的头像URL,绕开Auth缓存的问题:

suspend fun updateUserProfile(image: Uri, name: String): Result<String?> {
    return try {
        val storageRef = FirebaseStorage.getInstance().reference.child("Users/${firebaseAuth.currentUser?.uid}/${image.lastPathSegment}")
        // 等待图片上传完成
        storageRef.putFile(image).await()
        // 获取最新的下载URL
        val downloadUrl = storageRef.downloadUrl.await()
        // 更新用户资料
        val profileUpdates = userProfileChangeRequest {
            displayName = name
            photoUri = downloadUrl
        }
        firebaseAuth.currentUser?.updateProfile(profileUpdates)?.await()
        // 返回成功的下载URL
        Result.success(downloadUrl.toString())
    } catch (e: Exception) {
        e.printStackTrace()
        Result.failure(e)
    }
}

这里用Firebase的await()扩展函数(需要引入kotlinx-coroutines-play-services依赖)替代CompletableDeferred,逻辑更直观,避免多次触发完成信号。

2. 优化Compose状态更新逻辑

直接用返回的最新URL更新user状态,不再依赖getSignedInUser():

val singlePhotoPickerLauncher = rememberLauncherForActivityResult(
    contract = ActivityResultContracts.PickVisualMedia(),
    onResult = { uri ->
        if(uri != null) {
            scope.launch {
                val result = signInEmailVM.updateUserProfile(image = uri, name = "BRBX")
                if(result.isSuccess) {
                    Toast.makeText(
                        context,
                        "Изменения сохранены",
                        Toast.LENGTH_SHORT
                    ).show()
                    // 用copy创建新User实例,触发Compose重组
                    user = user.copy(
                        profilePictureUrl = result.getOrNull(),
                        userName = "BRBX"
                    )
                } else {
                    Toast.makeText(
                        context,
                        "Что-то пошло не так",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
        }
    }
)

注意User类要定义为data class,这样copy()方法能正确生成新实例,让Compose检测到状态变化触发重组。

3. 解决AsyncImage缓存问题

如果新图片和旧图片使用相同的存储路径,Coil的AsyncImage会缓存旧图。可以给URL加个时间戳参数强制刷新:

AsyncImage(
    model = "${user.profilePictureUrl}?t=${System.currentTimeMillis()}",
    contentDescription = "Profile picture",
    modifier = Modifier.fillMaxSize(),
    contentScale = ContentScale.Crop
)
额外依赖

要让Firebase API支持协程await()调用,需要在gradle里添加:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3"

内容的提问来源于stack exchange,提问作者Егор Сауткин

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 08:09:55