firebase 用户注册后程序不会继续

Program wont progress after firebase user registration

此 activity 在 firebase auth 中注册用户,在实时数据库中上传信息并在存储中上传用户图片。 这段代码(我不知道为什么)在注册用户时卡住了。如果您看到了,我已经添加了 Log 语句来中断整个过程。日志就像

STARTING PROCESS
BEFORE 
INSIDE 

没有其他声明。我想我正确地使用了协程,但我不知道为什么这个程序没有比这个更进一步 ^。我应该使用回调吗?我是否以错误的方式使用协程?如果有任何其他建议,我们将不胜感激。

class SignUpActivity : AppCompatActivity() {
    private lateinit var binding: ActivitySignUpBinding
    private lateinit var firebaseAuth : FirebaseAuth
    private lateinit var firebaseStorage: FirebaseStorage
    private lateinit var firebaseDatabase: FirebaseDatabase
    val TAG ="SIGNUPATAG"
    var selectedPhoto : Uri? = null
    var IMAGE_RESPONE_CODE = 1;
    var isOk = false;
    val imageUrl : String = "."
    var userUID = "."
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivitySignUpBinding.inflate(layoutInflater)
        setContentView(binding.root)
        firebaseAuth = FirebaseAuth.getInstance()
        binding.signupTvSelectPhoto.setOnClickListener {
            val intent = Intent();
            intent.type = "image/*"
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,"Select Pic"),IMAGE_RESPONE_CODE)
        }
        binding.signupBtnSignUp.setOnClickListener {
            val email = binding.signupEtvEmail.text.toString()
            if(email.isEmpty() || !Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
                binding.signupEtvEmail.error = "Invalid Email Address"
                binding.signupEtvEmail.requestFocus()
                return@setOnClickListener
            }
            if(binding.signupEtvName.text.length < 3) {
                binding.signupEtvName.error= "Name should at least have 3 characters"
                binding.signupEtvName.requestFocus()
                return@setOnClickListener
            }

            val password = binding.signupEtvPassword.text.toString()
            if(password.length < 4) {
                binding.signupEtvPassword.error = "Password should at least have 4 characters."
                binding.signupEtvPassword.requestFocus()
                return@setOnClickListener
            }

            // All Okay
            Log.d(TAG,"STARTING PROCESS")
            binding.pbSignup.visibility = View.VISIBLE
            createAccount(email,password,binding.signupEtvName.text.toString())
        }

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if(requestCode == 1) {
            if(data != null) {
                selectedPhoto = data?.data
                binding.signupImgvPhoto.setImageURI(selectedPhoto)
            }
            else {
                val context = this
                selectedPhoto = Uri.parse(
                    ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
                        + context.getResources().getResourcePackageName(R.drawable.profilepicnormall) + '/'
                        + context.getResources().getResourceTypeName(R.drawable.profilepicnormall) + '/'
                        + context.getResources().getResourceEntryName(R.drawable.profilepicnormall) )
            }

        }
    }

    private fun createAccount(email : String, password : String,name:String) {
        val context = this
        selectedPhoto = Uri.parse(
            ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
                    + context.getResources().getResourcePackageName(R.drawable.profilepicnormall) + '/'
                    + context.getResources().getResourceTypeName(R.drawable.profilepicnormall) + '/'
                    + context.getResources().getResourceEntryName(R.drawable.profilepicnormall) )
        lifecycleScope.async(Dispatchers.Main) {

            async {
                create(email,password)
            }.await()
            Log.d(TAG,"The isOk is $isOk")
            if(isOk){
                async {
                    Log.d(TAG,"in 1 async")
                    uploadImage()
                }.await()
                async {
                    Log.d(TAG,"in 2 async")
                    uploadDataToRealtimeDatabase(userUID,email,name,imageUrl)
                }.await()
                binding.pbSignup.visibility = View.GONE
                val intent = Intent(applicationContext,MainActivity::class.java)
                startActivity(intent)
                finish()
            }
            binding.pbSignup.visibility = View.GONE

        }
    }

    suspend fun create(email: String,password: String) {
        Log.d(TAG,"BEFORE")
        firebaseAuth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(parent) {task ->
            if(task.isSuccessful) {
                Toast.makeText(this@SignUpActivity,"SignUp Successful.",Toast.LENGTH_SHORT).show()
                isOk = true;
                userUID = firebaseAuth.currentUser!!.uid
                Log.d(TAG,"INSIDE")
                return@addOnCompleteListener
            }
            else {
                Log.d(TAG,"${task.exception} . ")
                Toast.makeText(this@SignUpActivity,"SignUp Not Successful.",Toast.LENGTH_SHORT).show()
            }
        }
        Log.d(TAG,"AFTER")
    }

    suspend fun uploadDataToRealtimeDatabase(UID:String,userEmail: String,userName : String,url:String) {
        Log.d(TAG,"in upload data")
        val ref = FirebaseDatabase.getInstance("https://firechat-931d2-default-rtdb.asia-southeast1.firebasedatabase.app/")
            .getReference("/users/$UID")
        val userinfo = UserInfo(userEmail,UID,userName,url)
        ref.setValue(userinfo).addOnSuccessListener {
            Log.d(TAG,"UPLOADED USER INFORMATION")
        }.addOnFailureListener{
            Log.d(TAG,"${it.message} $it")
        }
    }

    suspend fun uploadImage() : String  {
        Log.d(TAG,"in upload Image")
        val profilePicName = "${firebaseAuth.uid}.profileImage"
        var url = "."
        val storage_reference = FirebaseStorage.getInstance("gs://firechat-931d2.appspot.com").getReference("/ProfileImages/$profilePicName")
        storage_reference.putFile(selectedPhoto!!).continueWithTask { task ->
            if (!task.isSuccessful) {
                Log.d(TAG,"${task.exception}")
            }
            storage_reference.downloadUrl.addOnSuccessListener {
                url = it.toString()
            }.addOnFailureListener{
                Log.d(TAG,"$it ${it.message}")
            }
        }

        if(url.length < 2) {
            Log.d(TAG,"Going with default url.")
            url = "https://firebasestorage.googleapis.com/v0/b/firechat-931d2.appspot.com/o/ProfileImages%2FsqE6s03wgXQm7gl03xxQIM3JVQc2.profileImage?alt=media&token=640266a5-6611-4e09-b8ed-72ba8bdfdc1f"

        }
        Log.d(TAG,"returning the img url $url")
        return url
    }

}

在修复了您的代码的一些问题后,我只在虚拟应用程序中实现了注册部分,以下是我的观察结果:

No other statement

我的日志如下:

D/SIGNUPATAG: STARTING PROCESS
D/SIGNUPATAG: INSIDE
D/SIGNUPATAG: The isOk is true
D/SIGNUPATAG: in 1 async
D/SIGNUPATAG: in upload Image
D/SIGNUPATAG: in 2 async
D/SIGNUPATAG: in upload data

I think I am using coroutines correctly but I don't know why this program doesn't go further than this ^. Should I use callbacks? Am I using coroutines in a wrong way?

我认为您没有按预期使用协程,Firebase 调用已经是异步的,因此您不需要这样做,您应该使用内置的 Firebase 协程支持这个案例。我正在添加我在下面所做的更改。 (省略不需要任何更改的内容)

build.gradle

//firebase coroutines dependency
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.4.2"

SignUpActivity.kt

class SignUpActivity : AppCompatActivity() {

private lateinit var binding: ActivitySignUpBinding
.
.

override fun onCreate(savedInstanceState: Bundle?) {
.
.
}

private fun createAccount(email : String, password : String,name:String) {
     lifecycleScope.launch(Dispatchers.Main) {

        val createdUserJob = launch {
            try {
                Toast.makeText(this@SignUpActivity,"SignUp Successful.",Toast.LENGTH_SHORT).show()
                isOk = true;
                userUID = firebaseAuth.currentUser!!.uid
                Log.d(TAG,"INSIDE")
                firebaseAuth.createUserWithEmailAndPassword(email, password).await()
            } catch (e: Exception) {
                Toast.makeText(this@SignUpActivity,"SignUp Not Successful.",Toast.LENGTH_SHORT).show()
                e.printStackTrace()
            }
        }

        createdUserJob.join()

        Log.d(TAG,"The isOk is $isOk")
        if(isOk){
            val uploadImageJob = launch {
                Log.d(TAG,"in 1 async")
                uploadImage()
            }
            uploadImageJob.join()

            val uploadDataJob = launch {
                Log.d(TAG,"in 2 async")
                uploadDataToRealtimeDatabase(userUID,email,name,imageUrl)
            }
            uploadDataJob.join()

            binding.pbSignup.visibility = View.GONE
            val intent = Intent(applicationContext,MainActivity::class.java)
            startActivity(intent)
            finish()
        }
        binding.pbSignup.visibility = View.GONE

    }
}

    suspend fun uploadDataToRealtimeDatabase(UID:String,userEmail: String,userName : String,url:String) {
       Log.d(TAG,"in upload data")
       .
       .
     }

suspend fun uploadImage() : String  {
    Log.d(TAG,"in upload Image")
    .
    .
    return "dummy"
}
}

注意:我只测试了注册部分,图片上传和上传数据部分你需要自己测试,我去掉了create(email: String,password: String)还有方法。