흐르거나 흐르지 않습니까? Kotlin의 메시지 구독.

7677 단어 kotlinapicoroutines
이 짧은 기사에서는 콜백과 Flow를 통해 Kotlin에서 반응 구독을 수행하는 다양한 패턴에 대해 논의하고자 합니다.

어떤 종류의 개체 또는 구조가 있고 이 구조에 대한 변경 사항을 관찰하려고 한다고 가정해 보겠습니다.

이에 대한 고전적인 방법은 다음과 같습니다.

fun MyStructure.onChange(block: MyStructure.(Key) -> Unit)


그런 다음 다음과 같이 사용하십시오.

myStructure.onChange{ key ->
  println(get(key))
}


Kotlin 리시버 기능을 사용하면 클래식한 레이아웃이 더욱 깔끔해지기 때문에 의도적으로 해봤습니다. 미리 정의된 블록 기능을 사용할 수 있도록 변경 위치뿐만 아니라 변경된 개체에 대한 참조도 전달합니다.

이제 Kotlin 코루틴Flow API을 사용하여 어떻게 보이는지 살펴보겠습니다.

val MyStructure.changes: Flow<Key>

myStructure.changes.onEach{ key ->
  println(myStructure.get(key)
}.launchIn(scope)


Flow가 사용하기 훨씬 더 어려운 것 같습니다. 또한 CoroutineScope를 사용해야 합니다. 그리고 이를 위해 GlobalScope를 사용하면 안 되므로 스코프 수명 주기를 생각해야 합니다.

여기서 성능 문제에 대해 이야기하고 싶지 않습니다. 구독자가 너무 많으면 성능 문제이므로 다른 곳에서 이 문제를 해결해야 하지만 Flow 오버헤드도 더 클 것입니다.

반면에 Flow 의 이벤트로 변환을 쉽게 수행할 수 있습니다. 이와 같이:

myStructure.changes
  .filter{ key -> key.startsWith("my")}
  .map{ key -> myStructure.get(key)}
  .onEach{ value -> println(value)}
  .launchIn(scope)



하지만 사람들이 자주 잊는 문제가 있습니다.



구독을 했다면 구독도 취소하고 싶을 것입니다. 그렇지 않으면 메모리 누수(VM 의미에서)가 발생합니다. 누군가 구독 핸들을 보유하고 있기 때문에 일부 개체는 가비지 수집을 피합니다.

그래서 다음과 같은 코드를 작성합니다.

fun MyStructure.onChange(block: MyStructure.(Key) -> Unit)
fun MyStructure.removeChangeListener(block: MyStructure.(Key) -> Unit)


사실 이런 코드는 쓰지 마세요. 이 경우 올바른 리스너를 제거하기 위해 함수 동등성에 의존하고 함수 동등성이 신뢰할 수 없기 때문입니다. 또한 위에서 한 것처럼 람다를 통해 함수를 만들 수 없습니다. 별도로 생성하여 어딘가에 저장해야 합니다.

저는 보통 이렇게 합니다.

fun MyStructure.onChange(owner: Any, block: MyStructure.(Key) -> Unit)
fun MyStructure.removeChangeListener(owner: Any)


이 경우 owner 객체를 사용하여 콜백 홀더의 동등성을 확인합니다. 단일 소유자가 여러 콜백을 보유한 경우 모두 제거되고 용도가 있습니다. 이제 유일한 문제는 리스너가 더 이상 사용되지 않을 때 제거하는 것을 잊지 않는 것입니다(그리고 이는 Flow 의 경우와 같이 수명에 대해 생각해야 함을 의미합니다).

Flow에는 특정 구독 취소 방법이 필요하지 않습니다. 일반적으로 Flow 사용을 중지하면 더 이상 사용되지 않습니다. 또한 구독 작업을 취소하여 수동으로 구독을 취소할 수 있습니다.

val job = myStructure.changes.onEach{ key ->
  println(myStructure.get(key)
}.launchIn(scope)

job.cancel()


structured concurrency 로 인해 일반적으로 작업을 수동으로 취소하는 것에 대해 생각할 필요가 없습니다. 외부 범위가 닫히면 모든 하위 작업이 자동으로 취소됩니다. 따라서 평생 관리는 자동입니다.

그래도 코루틴 범위를 통해 수명을 관리해야 합니다(매우 편리함).


두 방법 모두 유효하며 다른 방법 대신 항상 그 중 하나를 사용해야 한다고 말할 수는 없습니다. 구독 취소를 잊을 위험이 없기 때문에 복잡한 시스템의 경우 Flow 방식을 선호한다고 생각합니다. 그러나 어떤 경우에는 범위에 신경쓰고 싶지 않을 수도 있습니다.


Chris StengerUnsplash이(가) 작성한 표지 이미지 사진

좋은 웹페이지 즐겨찾기