Kotlin Android Studio Подождите, пока функция завершит sh, прежде чем вызывать другую - PullRequest
0 голосов
/ 28 февраля 2020

Я пытаюсь выполнить функцию редактирования профиля, когда мне нужно дождаться, пока функция редактирования будет ЗАВЕРШЕНА, прежде чем запускать метод fini sh () и возвращаться к экрану активности профиля просмотра.

Однако у меня возникают проблемы, когда тост печатается только после завершения действия, и я уже направлен на действие профиля просмотра

        submitBtn.setOnClickListener()
    {
        runBlocking { // start main coroutine
            val job =GlobalScope.launch { // launch a new coroutine in background and continue
                delay(5000L)
                    val intent = Intent(this@editProfileActivity, viewProfileActivity::class.java)
                    finish()
                    startActivity(intent)

            }
            editAccountDetails() // main coroutine continues here immediately
            job.join()
        }

    }

. Мне нужно, чтобы editAccountDetails () был завершен до окончания sh () и началось выполнение действий. Может кто-нибудь сказать, что я делаю неправильно?

- Изменить код editaccountDetails () -

private fun editAccountDetails(){
        var username :String

        val usernameField = findViewById<EditText>(R.id.editTextUsername)

        userRefDoc = database.collection("users").document(userId!!)
        userRefDoc.get()
            .addOnSuccessListener { document ->
                if (document != null) {
                    username = (document.data?.getValue("fullname").toString())
                    if(usernameField.text.toString()!= username)
                    {
                        userRefDoc.update("fullname",usernameField.text.toString()).addOnFailureListener { e ->
                            val tempToast = Toast.makeText(this, "Error updating username", Toast.LENGTH_SHORT)
                            tempToast.setGravity(Gravity.CENTER, 0, 0)
                            tempToast.show()

                        }
                            .addOnSuccessListener { e ->
                                val tempToast=Toast.makeText(this, "Username has been updated", Toast.LENGTH_SHORT)
                                tempToast.setGravity(Gravity.CENTER, 0, 0)
                                tempToast.show()
                            }
                    }
                }
            }
        var email = (currentUser!!.email)
        val currentPasswordField = findViewById<EditText>(R.id.editCurrentPassword)
        val confirmPasswordField = findViewById<EditText>(R.id.editTextConfirmPassword)
        val newPasswordField = findViewById<EditText>(R.id.editTextNewPassword)
        val emailField = findViewById<EditText>(R.id.editTextEmail)

        if(emailField.text.toString() != email!! && newPasswordField.text.toString() != ""
            && confirmPasswordField.text.toString() != "") {
            if (currentPasswordField.text.toString() == "") {
                val tempToast = Toast.makeText(this, "Enter your current password", Toast.LENGTH_SHORT)
                tempToast.setGravity(Gravity.CENTER, 0, 0)
                return tempToast.show()
            } else {
                val pattern: Pattern
                val matcher: Matcher
                val specialCharacters = "-@%\\[\\}+'!/#$^?:;,\\(\"\\)~`.*=&\\{>\\]<_"
                val PASSWORD_REGEX =
                    "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[$specialCharacters])(?=\\S+$).{8,20}$"
                pattern = Pattern.compile(PASSWORD_REGEX)
                matcher = pattern.matcher(newPasswordField.text.toString())
                if (!matcher.matches()) {
                    val tempToast = Toast.makeText(
                        this,
                        "New password has to meet the requirements specified",
                        Toast.LENGTH_SHORT
                    )
                    tempToast.setGravity(Gravity.CENTER, 0, 0)
                    return tempToast.show()
                } else if (newPasswordField.text.toString() != confirmPasswordField.text.toString()) {
                    val tempToast = Toast.makeText(this, "New passwords do no match", Toast.LENGTH_SHORT)
                    tempToast.setGravity(Gravity.CENTER, 0, 0)
                    return tempToast.show()
                } else {
                    val newPassword = newPasswordField.text.toString()
                    val credential = EmailAuthProvider
                        .getCredential(email, currentPasswordField.text.toString())
                    currentUser?.reauthenticate(credential)
                        ?.addOnFailureListener {
                            Toast.makeText(
                                this,
                                "current password do not match",
                                Toast.LENGTH_LONG
                            ).show()
                        }
                        ?.addOnSuccessListener {
                            currentUser?.updateEmail(emailField.text.toString())
                                ?.addOnCompleteListener { task ->
                                    if (task.isSuccessful) {
                                        val tempToast = Toast.makeText(
                                            this,
                                            "Successfully updated email password",
                                            Toast.LENGTH_SHORT
                                        )
                                        tempToast.setGravity(Gravity.CENTER, 0, 0)
                                        tempToast.show()
                                        currentUser?.updatePassword(newPassword)
                                            ?.addOnCompleteListener { task2 ->
                                                if (task2.isSuccessful) {
                                                    val tempToast2 = Toast.makeText(
                                                        this,
                                                        "Successfully update password",
                                                        Toast.LENGTH_SHORT
                                                    )
                                                    tempToast2.setGravity(Gravity.CENTER, 0, 0)
                                                    tempToast2.show()
                                                }
                                            }
                                    }
                                }
                        }
                    return
                }

            }
        }

        //update email
        if(emailField.text.toString() != email){
            if(currentPasswordField.text.toString()=="")
            {
                val tempToast = Toast.makeText(this, "Enter your current password", Toast.LENGTH_SHORT)
                tempToast.setGravity(Gravity.CENTER, 0, 0)
                return tempToast.show()
            }
            else {
                val credential = EmailAuthProvider
                    .getCredential(email!!, currentPasswordField.text.toString())
                currentUser?.reauthenticate(credential)
                    ?.addOnFailureListener{
                        val tempToast = Toast.makeText(this, "current password do not match", Toast.LENGTH_SHORT)
                        tempToast.setGravity(Gravity.CENTER, 0, 0)
                        tempToast.show()}
                    ?.addOnSuccessListener {
                        currentUser?.updateEmail(emailField.text.toString())
                            ?.addOnCompleteListener { task ->
                                if (task.isSuccessful) {
                                    email = emailField.text.toString()
                                    val tempToast = Toast.makeText(this, "Successfully updated email", Toast.LENGTH_SHORT)
                                    tempToast.setGravity(Gravity.CENTER, 0, 0)
                                    tempToast.show()
                                } else {
                                    val tempToast = Toast.makeText(this, "Error updating email", Toast.LENGTH_SHORT)
                                    tempToast.setGravity(Gravity.CENTER, 0, 0)
                                    tempToast.show()
                                }
                            }
                    }

            }
        }
        //update password
        if(newPasswordField.text.toString() != "" && currentPasswordField.text.toString() != "" && confirmPasswordField.text.toString() != ""){
            val pattern: Pattern
            val matcher: Matcher
            val specialCharacters = "-@%\\[\\}+'!/#$^?:;,\\(\"\\)~`.*=&\\{>\\]<_"
            val PASSWORD_REGEX = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[$specialCharacters])(?=\\S+$).{8,20}$"
            pattern = Pattern.compile(PASSWORD_REGEX)
            matcher = pattern.matcher(newPasswordField.text.toString())
            if(!matcher.matches())
            {
                val tempToast = Toast.makeText(this, "New password has to meet the requirements specified", Toast.LENGTH_SHORT)
                tempToast.setGravity(Gravity.CENTER, 0, 0)
                return tempToast.show()
            }
            else if(newPasswordField.text.toString() != confirmPasswordField.text.toString())
            {
                val tempToast = Toast.makeText(this, "New passwords do no match", Toast.LENGTH_SHORT)
                tempToast.setGravity(Gravity.CENTER, 0, 0)
                return tempToast.show()
            }
            val newPassword = newPasswordField.text.toString()
            val credential = EmailAuthProvider
                .getCredential(email!!, currentPasswordField.text.toString())
            // Prompt the user to re-provide their sign-in credentials
            currentUser?.reauthenticate(credential)
                ?.addOnFailureListener {
                    val tempToast = Toast.makeText(this, "Current password does not tally", Toast.LENGTH_SHORT)
                    tempToast.setGravity(Gravity.CENTER, 0, 0)
                    tempToast.show()}
                ?.addOnSuccessListener {
                    currentUser?.updatePassword(newPassword)
                        ?.addOnCompleteListener { task ->
                            if (task.isSuccessful) {
                                val tempToast = Toast.makeText(this, "Successfully update password", Toast.LENGTH_LONG)
                                tempToast.setGravity(Gravity.CENTER, 0, 0)
                                tempToast.show()

                            }
                        }
                }
        }
    }

Ответы [ 2 ]

0 голосов
/ 28 февраля 2020

launch запускает сопрограмму, но не ждет результата. Ваши задачи, которые должны быть выполнены до событий сопрограммы, должны go в самом блоке launch.

runBlocking не должны использоваться в приложениях Android. Он предназначен почти исключительно для использования в функции main приложения JVM или в тестах. В противном случае он отрицает цель использования сопрограммы, потому что он блокирует поток.

GlobalScope не должен использоваться для запуска сопрограмм, которые захватывают действие или фрагмент, потому что тогда активность или фрагмент могут быть пропущены. Эта сопрограмма фиксирует активность, вызывая finish(). Вместо этого используйте lifecycleScope.

Так что если вы исправите все вышеперечисленное, у вас должно получиться что-то вроде:

submitBtn.setOnClickListener {
    lifecycleScope.launch {
        delay(5000L)
        editAccountDetails()
        val intent = Intent(this@editProfileActivity, viewProfileActivity::class.java)
        finish()
        startActivity(intent)
    }
}

Однако, поскольку я не знаю, что вы делаете с пятисекундная задержка или то, что делает editAccountDetails(), вам может потребоваться изменить ее.

Если editAccountDetails() - это длительная функция, которую вы не хотите блокировать основной поток, вы можете обернуть ее в блоке withContext(Dispatchers.Default){}, или сделайте его функцией приостановки, которая упаковывает свой собственный контент в withContext.

0 голосов
/ 28 февраля 2020

Если то, что вы пытаетесь достичь, это завершить sh действие только после того, как метод editAccountDetails завершен, и что методы занимают время. Вы можете вызвать этот метод внутри GlobalScope.launch {} и вызвать fini sh, когда возвращенное им задание будет завершено.

Ваш метод editAccountDetails (), кажется, выполняет вызовы API, я бы рекомендовал заменить GlobalScpoe.Launch на запуск (Dispatchers.Default)

Финальная версия выглядит примерно так:

submitBtn.setOnClickListener() {
    runBlocking {
        val job = launch(Dispatchers.Default) {
            editAccountDetails() 

        }
        job.join()
        val intent = Intent(this@editProfileActivity, viewProfileActivity::class.java)
        startActivity(intent)
        finish()
    }
}
...