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
相关产品推荐
相关产品推荐

