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

Firebase图片上传异常:registerForActivityResult替代后的问题

问题:类Instagram应用图片上传功能异常(registerForActivityResult替代onActivityForResult后)

开发类Instagram应用时,需实现图片加描述的上传功能。原教程使用已废弃的onActivityForResult方法,改用registerForActivityResult替代后,上传流程出现异常:选中图片后,回调中的it(图片Uri)无法在提交按钮的点击方法中调用,导致photoUri始终为空,无法完成图片上传。


修复方案

核心问题是未将图片选择回调中的Uri保存到可全局访问的变量(推荐用类成员变量替代全局变量,更符合Android开发规范),具体修改步骤如下:

1. 调整photoUri的作用域

将全局的photoUri改为CreatePostActivity类的成员变量,避免全局变量带来的生命周期问题:

class CreatePostActivity : ComponentActivity() {
    // 将全局变量移到类内部作为成员变量
    private var photoUri: Uri? = null
    // ... 其他成员变量
}

同时删除原来的全局变量声明:

// 删除这一行
// var photoUri : Uri? = null

2. 在图片选择回调中保存Uri

修改registerForActivityResult的回调逻辑,将选中的Uri赋值给成员变量photoUri,同时更新ImageView:

val getImage = registerForActivityResult(
    ActivityResultContracts.GetContent(),
    ActivityResultCallback { uri ->
        // 将选中的Uri保存到成员变量
        photoUri = uri
        // 更新ImageView显示图片
        uploadImageView.setImageURI(uri)
    }
)

3. 优化提交后的重置逻辑

上传成功后重置photoUri,防止用户重复提交同一图片:

// 上传成功后添加此行
photoUri = null // 重置Uri,避免重复提交

修改后的完整代码

package com.example.dndgroupfinder

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.contract.ActivityResultContracts
import com.example.dndgroupfinder.models.Post
import com.example.dndgroupfinder.models.User
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.storage.FirebaseStorage
import com.google.firebase.storage.StorageReference

private const val TAG = "createpost_activity"
private const val PICK_PHOTO_CODE = 1234

class CreatePostActivity : ComponentActivity() {

    private var signedInUser: User? = null
    private var photoUri: Uri? = null // 类成员变量保存图片Uri

    private lateinit var firestoreDatabase: FirebaseFirestore
    private lateinit var storageRef: StorageReference

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.createpost_activity)
        val uploadImageView = findViewById<ImageView>(R.id.uploadImageView)
        val btnSubmitPost = findViewById<Button>(R.id.btnSubmitPost)
        storageRef = FirebaseStorage.getInstance().reference

        firestoreDatabase = FirebaseFirestore.getInstance()

        // 获取当前登录用户信息
        firestoreDatabase.collection("users")
            .document(FirebaseAuth.getInstance().currentUser?.uid as String)
            .get()
            .addOnSuccessListener { userSnapshot ->
                signedInUser = userSnapshot.toObject(User::class.java)
                Log.i(TAG, "signed in user: $signedInUser")
            }
            .addOnFailureListener { exception ->
                Log.i(TAG, "Failure fetching signed in user", exception)
            }

        val btnSlctImg = findViewById<Button>(R.id.btnSlctImg)

        val getImage = registerForActivityResult(
            ActivityResultContracts.GetContent(),
            ActivityResultCallback { uri ->
                photoUri = uri // 保存选中的图片Uri
                uploadImageView.setImageURI(uri)
            }
        )

        btnSlctImg.setOnClickListener {
            Log.i(TAG, "Open up image picker in user device")
            getImage.launch("image/*")
        }

        btnSubmitPost.setOnClickListener {
            handleSubmitPostClick()
        }
    }

    private fun handleSubmitPostClick() {
        val uploadImageView = findViewById<ImageView>(R.id.uploadImageView)
        val btnSubmitPost = findViewById<Button>(R.id.btnSubmitPost)
        val postDescription = findViewById<EditText>(R.id.postDescription)

        // 检查图片是否选中
        if (photoUri == null) {
            Toast.makeText(this, "No photo has been selected", Toast.LENGTH_SHORT).show()
            return
        }
        // 检查描述是否为空
        if (postDescription.text.isBlank()) {
            Toast.makeText(this, "No description has been selected", Toast.LENGTH_SHORT).show()
            return
        }
        // 检查用户是否登录
        if (signedInUser == null) {
            Toast.makeText(this, "No user is signed in, please sign in before attempting to post", Toast.LENGTH_SHORT).show()
            return
        }

        btnSubmitPost.isEnabled = false

        // 上传图片到Firebase Storage并创建Post
        val photoUploadUri = photoUri as Uri
        val photoRef = storageRef.child("images/${System.currentTimeMillis()}-photo.jpg")
        photoRef.putFile(photoUploadUri)
            .continueWithTask { photoUploadTask ->
                Log.i(TAG, "Number of bytes uploaded: ${photoUploadTask.result?.bytesTransferred}")
                // 获取图片下载URL
                photoRef.downloadUrl
            }.continueWithTask { downloadUrlTask ->
                // 创建Post对象并添加到Firestore
                val post = Post(
                    postDescription.text.toString(),
                    downloadUrlTask.result.toString(),
                    System.currentTimeMillis(),
                    signedInUser
                )
                firestoreDatabase.collection("posts").add(post)
            }.addOnCompleteListener { postCreateTask ->
                btnSubmitPost.isEnabled = true
                if (!postCreateTask.isSuccessful) {
                    Log.e(TAG, "Exception during firebase operations", postCreateTask.exception)
                    Toast.makeText(this, "Failed to save post", Toast.LENGTH_SHORT).show()
                    return@addOnCompleteListener
                }
                // 重置界面状态
                postDescription.text.clear()
                uploadImageView.setImageResource(0)
                photoUri = null // 重置Uri,避免重复提交
                Toast.makeText(this, "Post has been successfully uploaded!", Toast.LENGTH_SHORT).show()
                val profileIntent = Intent(this, UserProfileActivity::class.java)
                profileIntent.putExtra(EXTRA_USERNAME, signedInUser?.username)
                startActivity(profileIntent)
                finish()
            }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 19:05:05