Двойные подписки на внутренний поток с потоком kotlin - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть следующая проблема с моим фрагментом кода ниже:

  1. Когда изменяется набор подключенных в настоящее время сканеров штрих-кода, set с подключенными в данный момент сканерами будет выдан поток scanners: Flow<Set<BarcodeScanner>>.

  2. Если я подключил один сканер, называемый А, и сканировал штрих-код, это нормально работает, и результат будет показан в текстовом представлении.

  3. Если я подключу дополнительное устройство, а затем снова выполню сканирование на устройстве А., я увижу результат сканирования 2 раза.

  4. Это выглядит таким образом, при каждом изменении набора <> в collect { scanner.scan() } создается дополнительная подписка потока, а предыдущий поток все еще остается на месте.

Как я могу решить эту проблему? Я уже весь день играл с разными операторами и т. Д. c ... Я использую Flow 1.2.2

 uiScope.launch { //CoroutineScope(Job() + Dispatchers.Main)
             scanners //Flow<Set<BarcodeScanner>> will emit the set of scanner, currently connected scanners, when one connects/disconnects
                .onEach {
                    txtView.text = "Barcode scanners: ${it.size}\n"
                }
                .flatMapMerge { // Flatten to Flow<BarcodeScanner>
                    it.asFlow()
                }
                .onEach { scanner ->
                    txtView.append("${scanner.name()} [${scanner.hashCode()}]\n")
                }
                .collect { scanner ->
                    //if a new Set<BarcodeScanner> is emitted, this Flow<Barcode> returned by scanner.scan() will be subscribed again, without removing the old stream
                    //resulting in multiple results on a single scan.
                    scanner.scan() //returns an Flow<Barcode>
                        .onEach { barcode ->
                            findViewById<TextView>(R.id.txtViewBarcodes).append("[${scanner.name()}]: ${barcode.value} (${barcode.type.description})\n")
                        }
                        .onCompletion {
                            Timber.i("[${scanner.name()}]: DISCONNECTED") //Never called
                        }
                        .launchIn(scanScope)
                }
        }
...