Опросный репозиторий с сопрограммными каналами - PullRequest
0 голосов
/ 20 апреля 2019

Я играю с сопрограммными каналами, и я хотел реализовать проект с опросом. Идея состоит в том, что модель представления будет прослушивать данные из хранилища, которое несколько раз опрашивает конечную точку.

Когда я передаю coroutineScope в хранилище, опрос работает, однако, когда я создаю новый хранилище coroutineSCope в хранилище, я вижу, что данные вводятся в канал, но они не принимаются в модели представления.

Так что это работает:

class PollingViewModel : ViewModel() {

    val counter = MutableLiveData<String>().apply { value = "uninitialized" }

    private val repository = Repository()

    init {
        viewModelScope.launch {
            val channel = repository.poll(this /* scope */)
            channel.consumeEach {
                Log.d("foo", "Viewmodel received [$it]")
                counter.postValue(it.toString())
            }
        }
    }
}

class Repository {

    private var startValue = 0

    suspend fun poll(coroutineScope: CoroutineScope) =
        coroutineScope.produce(capacity = Channel.CONFLATED) {
            while (true) {
                Log.d("foo", "Sending value [$startValue]")
                send(startValue++)
                delay(POLLING_PERIOD_MILLIS)
            }
        }

    companion object {
        private const val POLLING_PERIOD_MILLIS = 1000L
    }
}

Но это не так (viewmodel ничего не получает):

class PollingViewModel : ViewModel() {

    val counter = MutableLiveData<String>().apply { value = "uninitialized" }

    private val repository = Repository()

    init {
        viewModelScope.launch {
            repository.poll().consumeEach {
                Log.d("foo", "Viewmodel received [$it]")
                counter.postValue(it.toString())
            }
        }
    }
}

class Repository {

    private var startValue = 0

    suspend fun poll() = coroutineScope {
        produce(capacity = Channel.CONFLATED) {
            while (true) {
                Log.d("foo", "Sending value [$startValue]")
                send(startValue++)
                delay(POLLING_PERIOD_MILLIS)
            }
        }
    }

    companion object {
        private const val POLLING_PERIOD_MILLIS = 1000L
    }
}

В чем проблема с созданием coroutineScope на уровне хранилища?

1 Ответ

0 голосов
/ 21 апреля 2019

Похоже, решение заключается в создании нового CoroutineContext в хранилище:

class Repository {

    private var startValue = 0
    private val context: CoroutineContext by lazy(LazyThreadSafetyMode.NONE) {
        Job() + Dispatchers.IO
    }

    suspend fun poll(): ReceiveChannel<Int> = coroutineScope {
        produce(
            context = context,
            capacity = Channel.CONFLATED
        ) {
            while (true) {
                send(startValue++)
                delay(POLLING_PERIOD_MILLIS)
            }
        }
    }

    companion object {
        private const val POLLING_PERIOD_MILLIS = 1000L
    }
}
...