https://kotlinlang.org logo
Title
s

Seri

08/29/2018, 5:24 PM
How would you all expose state stored inside of an Actor? Ideally, I’d be able to observe changes to variables inside the Actor from other classes. I’ve got this implemented already in Android using LiveData, but it’s a bit hacky
g

gildor

08/29/2018, 5:27 PM
Actor class can expose ReceiveChannel (open connection on BroadcastChannel
s

Seri

08/29/2018, 5:42 PM
In this case, I have an Actor inside of an Android ViewModel that takes in sealed class Events and computes the next UI State. I need some way to communicate these state changes to my Fragment/Activity
w

withoutclass

08/29/2018, 6:21 PM
You need two channels for that type of thing. For our ViewModel conversion, the VM owns both receiving channels from the View and sending channels to the view. Have your actor take the channel that communicates back to your activity as an argument and then pump the event objects down it for the activity to listen for.
We’re doing nearly this exact thing in a production app right now, except without actors
s

Seri

08/29/2018, 6:44 PM
import kotlinx.coroutines.experimental.channels.*
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking

fun main(args: Array<String>)  = runBlocking<Unit> {
    // Create the listener
    val listener = ConflatedBroadcastChannel<Int>()

    // Create the actor
    val actor = counterActor(listener)

    // Send some events
    launch{
        repeat(5) {
            actor.send(Event.Increment)
            delay(250)
        }
        repeat(5) {
            actor.send(Event.Decrement)
            delay(250)
        }
        actor.close()
    }

    // Print out the counter
    for (i in listener.openSubscription()) {
        println("The counter is $i")
    }
}

fun counterActor(counterReceiver: SendChannel<Int>) = actor<Event> {
    var counter = 0
    for (msg in channel) {
        counter = when (msg) {
            is Event.Increment -> counter + 1
            is Event.Decrement -> counter - 1
        }.also {
            counterReceiver.send(it)
        }
    }
    counterReceiver.close()
}

sealed class Event {
    object Increment: Event()
    object Decrement: Event()
}
Thanks for the tip, @withoutclass! I’ve got the above proof of concept built out.
w

withoutclass

08/29/2018, 6:45 PM
👍