Kotlin如何更新Firebase实时数据库指定子节点userProfilePic
Firebase Realtime Database userProfilePic 字段更新方案
我的Firebase Realtime Database结构如下所示:
我想要更新该结构中的userProfilePic字段,尝试了多种实现方式始终更新失败,原有代码如下:
database.getReference() .child("User") .child(FirebaseAuth.getInstance().uid.toString()) .child("userProfilePic") .setValue(uri) .addOnSuccessListener { } .addOnFailureListener { Toast.makeText(this,it.message,Toast.LENGTH_SHORT).show() }
失败核心原因
直接传入setValue(uri)的uri如果是相册/相机返回的Android本地Uri对象(content://开头的本地文件路径),会直接写入失败。Firebase Realtime Database仅支持存储字符串、数字、布尔值、Map、List等基础可序列化类型,不会自动解析本地文件路径,也无法让其他用户访问设备本地的文件地址。
另外代码中直接对FirebaseAuth.getInstance().uid调用toString()存在隐患:如果用户未登录uid为null,会拼接成路径User/null/userProfilePic,写入错误节点。
正确实现步骤
- 先将本地头像图片上传到Firebase Storage,拿到云端可公开访问的下载链接字符串
- 校验当前登录用户UID有效性,避免路径拼接错误
- 将字符串格式的下载链接写入对应数据库节点
完整可运行代码
// 初始化Storage存储路径,按uid命名头像避免文件重复 val profilePicStorageRef = FirebaseStorage.getInstance() .getReference("user_avatars/${FirebaseAuth.getInstance().currentUser?.uid}") // 第一步:上传本地头像到Firebase Storage profilePicStorageRef.putFile(uri) // 此处uri为本地选择/拍摄得到的图片Uri .addOnSuccessListener { uploadResult -> // 上传完成后获取图片的公网访问链接 uploadResult.metadata?.reference?.downloadUrl ?.addOnSuccessListener { cloudDownloadUri -> val avatarUrl = cloudDownloadUri.toString() // 校验登录状态,避免空uid val currentUser = FirebaseAuth.getInstance().currentUser if (currentUser == null) { Toast.makeText(this@YourActivity, "登录状态失效,请重新登录", Toast.LENGTH_SHORT).show() return@addOnSuccessListener } // 第二步:写入字符串链接到Realtime Database database.getReference("User") .child(currentUser.uid) .child("userProfilePic") .setValue(avatarUrl) .addOnSuccessListener { Toast.makeText(this@YourActivity, "头像更新成功", Toast.LENGTH_SHORT).show() } .addOnFailureListener { dbError -> Toast.makeText(this@YourActivity, "更新失败:${dbError.message}", Toast.LENGTH_SHORT).show() } } } .addOnFailureListener { uploadError -> Toast.makeText(this@YourActivity, "图片上传失败:${uploadError.message}", Toast.LENGTH_SHORT).show() }
额外排查项
- 核对节点名称完全匹配:注意节点名大小写,如果数据库实际根节点为
Users(复数形式)、字段名为下划线格式user_profile_pic,代码节点名不匹配会写入到新的独立节点,表现为原字段未更新 - 检查数据库安全规则配置,避免权限拦截,测试阶段可配置为仅用户本人可读写自己的数据:
{ "rules": { "User": { "$uid": { ".read": "$uid === auth.uid", ".write": "$uid === auth.uid" } } } }
- 如果不需要上传本地图片,仅需更新为已有的网络图片地址,直接将地址转为字符串类型传入
setValue()即可,不要传入Uri类型对象。
内容的提问来源于stack exchange,提问作者Muhammad Hamza
相关产品推荐
相关产品推荐

