>source

Flow에서 너무 일찍 취소하려고 할 때 이상한 동작을 발견했습니다. 다음 예를 살펴보십시오.

이것은 정수 값을 방출하는 간단한 흐름입니다.

 private fun createFlow() = flow {
        repeat(10000) {
            emit(it)
        }
    }

그런 다음 createFlow 이 코드를 사용하는 기능

 CoroutineScope(Dispatchers.Main).launch {
            createFlow().collect {
                Log.i("Main", "$it isActive $isActive")
                if (it == 2) {
                    cancel()
                }
            }
        }

이것은 인쇄 된 것입니다

0 isActive true
1 isActive true
2 isActive true
3 isActive false
4 isActive false
etc...etc

이제 흐름이 2의 값에 도달하면 정수 방출을 중지해야하지만 대신 실제로 isActive 플래그를 false로 전환하고 달리 중지하지 않고 계속 방출합니다.

방출 사이에 지연을 추가하면 흐름이 예상대로 작동합니다.

private fun createFlow() = flow {
    repeat(10000) {
        delay(500) //add a delay
        emit(it)
    }
}

이것은 흐름을 다시 호출 한 후 출력되는 것입니다 (예상되는 동작).

0 isActive true
1 isActive true
2 isActive true

지연을 추가하지 않고 지정된 값에서 정확히 유량 방출을 취소하려면 어떻게해야합니까?

  • 답변 # 1

    이 관련 문제에서 해결 방법을 발견했습니다.

    나는 모든 것을 교체했습니다 collect 와 함께 safeCollect 내 프로젝트의 기능 :

    /**
     * Only proceed with the given action if the coroutine has not been cancelled.
     * Necessary because Flow.collect receives items even after coroutine was cancelled
     * https://github.com/Kotlin/kotlinx.coroutines/issues/1265
     */
    suspend inline fun <T> Flow<T>.safeCollect(crossinline action: suspend (T) -> Unit) {
      collect {
        coroutineContext.ensureActive()
        action(it)
      }
    }
    
    

  • 답변 # 2

    나는 최근에 이것을 생각 해냈다

    일시 중단 지점에 도달하고 코드에 그러한 지점이없는 경우에만 실제로 취소되는 것 같습니다.

    이를 해결하려면 방출 사이에 yield ()를 추가하거나 delay (100)와 같은 다른 일시 중지 함수를 추가하십시오.

  • 이전 database - 한 컬렉션의 필드를 조건부로 복사하고 PyMongo를 사용하여 MongoDB의 다른 컬렉션에 추가하는 방법은 무엇입니까?
  • 다음 css - - : after 및 :: pseudo가 주 요소와 정렬되지 않는 이유는 무엇입니까?