2017-10-12 1 views
0

리스너 용으로 producer을 생성하려고합니다. 내 코드는 다음과청취자 용 청취자

suspend fun foo() = produce{ 
    someEvent.addListener { 
     this.send(it) 
    } 
} 

처럼 보인다하지만 의미가 오류 Suspension functions can be called only within coroutine납니다. 내 질문은. 코 루틴을 사용하여이 패턴을 구현할 수있는 방법이 있습니까? 방금 에게 가장 최근의 이벤트를 수신 할 경우, 당신은 으로 융합 채널과 offer 방법을 사용한다

:

답변

2

은 당신이 달성하려고하는 내용에 따라이를 구현하는 방법은 여러 가지가 있습니다 그가는 요리는 그것을 성공 :

fun foo() = produce<T>(capacity = Channel.CONFLATED) { 
    someEvent.addListener { 
     offer(it) 
    } 
} 

를 그 다음 당신의 선택은 이벤트 프로듀서의 동작에 따라, 모든 이벤트를 수신하는 것이 중요합니다. 여기에서 숙고해야 할 핵심 질문은 이벤트 프로듀서가 "논스톱"이벤트를 많이 생성하기 시작하면 어떻게 될지입니다. 일반적으로 대부분의 "동기식"이벤트 생성기는 명시적인 백 프레셔 신호를 지원하지 않지만 암시 적 백 프레셔 신호를 지원합니다. 리스너가 느리거나 스레드를 차단하면 속도가 느려집니다. 따라서, 일반적으로 다음과 같은 솔루션은 동기 이벤트 생산자 완벽하게 작동합니다 : 이벤트의 배치는 한 번에 생성 될 때이 경우이있는 경우

fun foo() = produce<T>() { 
    someEvent.addListener { 
     runBlocking { send(it) } 
    } 
} 

당신은 또한 성능 최적화로 produce 빌더에 매개 변수로 긍정적 capacity = xxx를 지정할 수 있습니다 제작자를 차단하고 싶지는 않지만 소비자가 자신의 페이스대로 처리하도록하십시오.

드문 경우이지만 제작자가 암시 적 블로킹 백 프레셔 신호를 이해하지 못하는 경우 (내부 동기화없이 일종의 멀티 스레드 처리로 이벤트를 생성하는 경우) 무제한 용량의 채널을 offer과 함께 사용할 수 있습니다 당신의 생산자가 지원하는 경우

fun foo() = produce<T>(capacity = Channel.UNLIMITED) { 
    someEvent.addListener { 
     offer(it) 
    } 
} 

신호 (기능 반응 스트림 등)을 명시 적으로 다시 압력은, 다음에 특수 어댑터를 사용해야하지만, 생산자가 소비자를 능가합니다 경우 메모리를 고갈 위험이 있음을 조심 코 루틴으로 /에서 백 압력 신호를 제대로 전송하십시오. kotlinx.coroutines 라이브러리에는 이러한 용도로 다양한 반응 라이브러리가있는 여러 가지 기본 통합 모듈이 있습니다. here을 참조하십시오.

참고 : 당신이 suspend 수정하여 foo 기능을 표시해서는 안된다. foo의 호출은 어쨌든 호출자를 일시 중단하지 않습니다. 즉시 (동 기적으로) 생성자 코 루틴을 시작합니다.

코 루틴과 다른 종류의 채널에 대해 자세히 알아 보려면 the guide on kotlinx.coroutines을 공부하는 것이 좋습니다.

+0

철저한 답변 주셔서 감사합니다 :) –