带有异步调用的ListenableWorker startWork不会达到断点

时间:2019-02-12 11:21:57

标签: android kotlin

我正在使用Firestore在数据库中注册用户。 为了方便起见,我决定将所有注册代码放在ListenableWorker中,以利用WorkManager库。

此类称为RegisterUserWorker。 在此任务中,我执行对Firestore的调用以将用户添加到数据库:

class RegisterTask(ctx: Context, params: WorkerParameters) : ListenableWorker(ctx, params) {

    private val auth = FirebaseAuth.getInstance()

    private lateinit var countDownLatch: CountDownLatch

    private val taskResult = arrayOf(Result.failure())

    private lateinit var emailAddress: String

    private lateinit var password: String

        override fun startWork(): ListenableFuture<Result> {
        // Based on this post: https://stackoverflow.com/a/50425201

        println("run attempt count: $runAttemptCount")
        countDownLatch = CountDownLatch(1)

        val username = inputData.getString("username")!!
        password = inputData.getString("password")!!
        emailAddress = inputData.getString("emailAddress")!!
        val countryOfOrigin = inputData.getString("countryOfOrigin")!!
        val dateOfBirth = inputData.getString("dateOfBirth")!!

       // var awaitsCountDown = false


        auth.createUserWithEmailAndPassword(emailAddress, password).addOnCompleteListener { task ->
            // awaitsCountDown = true
            if (task.isSuccessful) {
                // Sign in success, update UI with the signed-in user's information
                Log.w(this.TAG(), "createUserWithEmailAndPassword:success")
                val uid = FirebaseAuth.getInstance().uid
                if (uid is String) {
                    // uid exists because user creation succeeded
                    val user = User(
                            // Usernames are case insensitive
                            username = username,
                            userId = uid,
                            emailAddress = emailAddress,
                            countryOfOrigin = countryOfOrigin,
                            dateOfBirth = dateOfBirth,
                            accountActivated = false
                    )
                    registerUser(user, password)
                } else {
                    taskResult[0] = Result.failure(Data.Builder().putString("error", "AUTHENTICATION_FAILED").build())
                    countDownLatch.countDown()
                }
            } else {
                // Remove signed-in user and tell that the registration failed
                Log.w(this.TAG(), "createUserWithEmail:failure", task.exception)
                countDownLatch.countDown()
            }
        }.addOnCanceledListener {
            Log.e(this.TAG(), "createUserWithEmail:cancelled")
        }


//        if (awaitsCountDown){
        try {
            countDownLatch.await()
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
//        }

        val result = SettableFuture.create<Result>()
        result.set(taskResult[0])
        return result
    }

启动并观察此工作程序的代码如下:

val inputData = Data.Builder()
        .putString("username", register_username_input.value.trim().toLowerCase())
        .putString("password", register_password_input.value)
        .putString("emailAddress", register_email.value)
        .putString("countryOfOrigin", register_country_of_origin.value)
        .putString("dateOfBirth", register_date_of_birth.value)
        .build()
val registerUserTask = OneTimeWorkRequest.Builder(RegisterTask::class.java)
        .setInputData(inputData)
        .build()
// Make sure only the earliest deployed task runs
WorkManager.getInstance().beginUniqueWork("registerUserTask",
        ExistingWorkPolicy.REPLACE, registerUserTask).enqueue()
// See https://medium.com/@mfahadbuttt/work-manager-by-android-jetpack-eae1b181d0fd
WorkManager.getInstance().getWorkInfoByIdLiveData(registerUserTask.id).observeForever { workInfo ->
    if (workInfo.state.isFinished) {
        // State considered finished, determine which state it is
        val outputData = workInfo.outputData
        when (workInfo.state) {
            WorkInfo.State.SUCCEEDED -> Toast.makeText(applicationContext, "An email has been sent to your account",
                    Toast.LENGTH_LONG).show()
            else -> {
                Log.i(this.TAG(), "State: ${workInfo.state}, output data $outputData")
                Toast.makeText(applicationContext, "Account registration failed",
                        Toast.LENGTH_LONG).show()
            }
        }
    }
}

为了能够在调用Firestore的异步调用后在同一个函数中返回结果,我使用了CountDownlatch(基于this answer)。执行代码后,我发现OnCompleteLister中的所有断点均未命中。 因此,代码将永远挂在countDownLatch.await()语句上。 但是,通过在Firestore控制台中查看,我验证了该用户确实在“身份验证”选项卡中存在,这意味着应该已命中该断点。

我试图:

  • 将断点挂起设置更改为挂起所有线程,这不会更改任何内容
  • 引入一个布尔值,该布尔值指示我们是否输入了onCompleteLister,并且仅在适当时才调用countDownLatch.countDown()。我注意到在函数返回之后,断点会被命中,但是由于函数已经返回,因此更新后的result并不会执行任何操作。

编辑

我遵循in this post中描述的方法解决了我的问题。

0 个答案:

没有答案