Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何避免在任务完成之前导航到下一个?_Android_Kotlin_Task - Fatal编程技术网

Android 如何避免在任务完成之前导航到下一个?

Android 如何避免在任务完成之前导航到下一个?,android,kotlin,task,Android,Kotlin,Task,我在其中一个片段上有以下clickListener binding.btnCamera.setOnClickListener { val photo = takePhoto() val prediction = MachineLearning().predict(photo) val action = FirstFragmentDirections.actionFirstToSecond(prediction)

我在其中一个片段上有以下
clickListener

 binding.btnCamera.setOnClickListener {
        val photo = takePhoto()
        
        val prediction = MachineLearning().predict(photo)
       
        val action = FirstFragmentDirections.actionFirstToSecond(prediction)

        findNavController().navigate(action)
}
MachinLearing.kt
predict()
函数如下所示,其中包含异步执行的任务

fun predict(photo: Bitmap): Boolean {

    val conditions = CustomModelDownloadConditions.Builder()
        .requireWifi()
        .build()

    FirebaseModelDownloader.getInstance()
        .getModel(modelName, DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND, conditions)
        .addOnSuccessListener { customModel ->
           ...
        }
        .addOnFailureListener{
           ...
        }
    ...
}
我想停止导航到下一个片段,直到
predict()
中的
任务完成

由于
任务的异步性质
<代码>任务
在片段导航之前完成的可能性较小。如果发生了片段导航,则将在当前片段中调用
onDestroy()
,从而导致
MachineLearning
对象被垃圾收集,因此
任务
完全不会完成


那么我怎么能在片段导航之前等待任务完成呢?

方法
addOnCompleteListener
addOnFailureListener
都是回调。这意味着它是异步的,因此无论方法
predict
返回什么,它都可能在触发这些方法之前或之后发生。有两个选项:添加另一个回调或将其转换为挂起

回拨:

fun predict(photo: Bitmap, predictionDelegate: (Boolean) -> Unit) {
    //...
    addOnCompleteListener { model ->
        //do your thing and then call the callback
        predictionDelegate.invoke(yourCalculatedBoolean)
    }
    .addOnFailureListener...//do the same

}
然后我要说:

MachineLearning().predict(photo) { prediction ->
    val action = FirstFragmentDirections.actionFirstToSecond(prediction)

    findNavController().navigate(action)
}
另一种选择是将其挂起:

suspend fun predict(): Boolean() {
    val deferred = CompletableDeferred<Boolean()
    //your thing
    enter code here
    .addOnSuccessListener { model ->
        //do your thing and then update the defferred
        deferred.complete(yourCalculatedBoolean)
    }
    .addOnFailureListener...//do the same

    return deferred.await()
}

我假设您由于绑定而处于
片段
活动
,因此您应该具有
生命周期范围

方法
addOnCompleteListener
addOnFailureListener
都是回调。这意味着它是异步的,因此无论方法
predict
返回什么,它都可能在触发这些方法之前或之后发生。有两个选项:添加另一个回调或将其转换为挂起

回拨:

fun predict(photo: Bitmap, predictionDelegate: (Boolean) -> Unit) {
    //...
    addOnCompleteListener { model ->
        //do your thing and then call the callback
        predictionDelegate.invoke(yourCalculatedBoolean)
    }
    .addOnFailureListener...//do the same

}
然后我要说:

MachineLearning().predict(photo) { prediction ->
    val action = FirstFragmentDirections.actionFirstToSecond(prediction)

    findNavController().navigate(action)
}
另一种选择是将其挂起:

suspend fun predict(): Boolean() {
    val deferred = CompletableDeferred<Boolean()
    //your thing
    enter code here
    .addOnSuccessListener { model ->
        //do your thing and then update the defferred
        deferred.complete(yourCalculatedBoolean)
    }
    .addOnFailureListener...//do the same

    return deferred.await()
}

我假设由于绑定,您处于
片段
活动
,因此您应该具有
lifecycleScope

基本上,您应该将回调传递到
predict
,当工作完成时触发。但是,当您使用Kotlin时,我建议您研究挂起函数。@user158我的最佳猜测是,因为人们看到了数百个异步问题,这些问题不是问题,而是缺乏对异步编程工作原理的理解。检查我的答案,这可能会对你有所帮助。@user158为什么混合主题是一个有效的借口?@user158你不知道主题a,但你提到主题B,提到主题B并不能弥补事先不知道,你应该将回调传递到
predict
,当工作完成时触发。但是,当您使用Kotlin时,我建议您研究挂起函数。@user158我的最佳猜测是,因为人们看到了数百个异步问题,这些问题不是问题,而是缺乏对异步编程工作原理的理解。检查我的答案,这可能会对你有所帮助。@user158为什么混合主题会是一个有效的借口?@user158你不知道主题a,但你提到主题B,提到主题B并不能弥补你不知道A@user158看一看again@user158再看看