Расходный канал - PullRequest
       6

Расходный канал

0 голосов
/ 09 июня 2018

Use Case

Фрагмент Android, который потребляет предметы T из ReceiveChannel<T>.После употребления T s следует удалить из ReceiveChannel<T>.

Мне нужен ReceiveChannel<T>, который поддерживает потребление предметов из него.Он должен функционировать как очередь FIFO.

В настоящее время я подключаюсь к каналу из своего пользовательского интерфейса, например:

launch(uiJob) { channel.consumeEach{ /** ... */ } }

Я отключаюсь, вызывая uiJob.cancel().

Желаемое поведение:

val channel = Channel<Int>(UNLIMITED)

channel.send(1)
channel.send(2)
// ui attaches, receives `1` and `2`
channel.send(3) // ui immediately receives `3`
// ui detaches
channel.send(4)
channel.send(5)
// ui attaches, receiving `4` and `5`

К сожалению, когда я отсоединяюсь от канала, канал закрывается.Это заставляет .send(4) и .send(5) генерировать исключения, потому что канал закрыт.Я хочу иметь возможность отсоединиться от канала, чтобы он оставался пригодным для использования.Как я могу это сделать?

Channel<Int>(UNLIMITED) идеально подходит для моего варианта использования, за исключением , который закрывает канал, когда он отписывается.Я хочу, чтобы канал оставался открытым.Это возможно?

Ответы [ 2 ]

0 голосов
/ 09 июня 2018

Вы можете использовать BroadcastChannel.Однако вам нужно указать ограниченный размер (например, 1), так как UNLIMITED и 0 (для рандеву) не поддерживаются BroadcastChannel.

. Вы также можете использовать ConflatedBroadcastChannel, который всегда дает последнее значение, которое он имел для новых подписчиков, как LiveData.

Кстати, разве это важно, если ваш новый экземпляр Fragment получает только последнее значение?Если нет, просто перейдите с ConflatedBroadcastChannel.В противном случае ни один из BroacastChannel s может не подходить для вашего варианта использования (попробуйте и посмотрите, получите ли вы нужное поведение).

0 голосов
/ 09 июня 2018

Channel.consumeEach вызывает метод Channel.consume метод, который имеет эту строку в документации:

Гарантирует, что данный блок потребляет все элементы из данного канала , всегда вызывая отмену послевыполнение блока .

Таким образом, решение состоит в том, чтобы просто не использовать consume[Each].Например, вы можете сделать:

launch(uiJob) { for (it in channel) { /** ... */ } }

...