Here are few benefits of channels over rx (IMO):.
* Can handle null emissions (and in a safe way, thanks to Kotlin type system)
* Threading is explicit. With Rx, it's often hard to know on what thread pool each piece of code is executed
* ReceiveChannel and SendChannel use [on-site variance](
https://kotlinlang.org/docs/reference/generics.html#declaration-site-variance) which can make thinks easier when generic variance is involved.
* It is (a lot) easier to create custom operators with channels.
* When it comes to parallelism, Coroutines are (IMO) way easier to use and produce clearer code.
* pipeline pattern out of the box.
So far, I haven't run in a use case that Rx solved and I couldn't handle in a nice and easy way with Channels. If you know one, i would be interested to look at it.