Hector
Hector

Reputation: 5356

How to encapsulate Android Coroutine Actor and still associate it with viewModelScope

I'm investigating Kotlin Coroutine Actors in my current Android project.

Currently I have the following classes

Messenger:

import kotlinx.coroutines.channels.SendChannel
import org.research.development.intentions.action.Sendable

class Messenger<T>(private val sendChannel: SendChannel<T>) : Sendable<T> {

    override suspend fun send(message: T) {
        sendChannel.send(message)
    }
}

ViewModel

abstract class BaseViewModel<I, S>(initialState: S) : ViewModel(), ViewModelable<I, S> {

    private val sendChannel: SendChannel<I> = viewModelScope.actor {
        for (message in channel) {
            dispatch(message)
        }
    }

    protected val internalStateFlow = MutableStateFlow(initialState)
    val stateFlow: StateFlow<S>
        get() = internalStateFlow

    private val messenger: Sendable<I> = Messenger(sendChannel)

    override fun send(message: I) {
        viewModelScope.launch(Dispatchers.IO) {
            messenger.send(message)
        }
    }
}

What I would like is to have the Actors sendChannel declared within my Messenger class

    import kotlinx.coroutines.channels.SendChannel
    import org.research.development.intentions.action.Sendable
    
    class Messenger<T>() : Sendable<T> {

        private val sendChannel: SendChannel<I> = actor { // viewModelScope????
            for (message in channel) {
                dispatch(message) // HOW DO I CALL THIS METHOD????
            }
        }
    
        override suspend fun send(message: T) {
            sendChannel.send(message)
        }
    }

However this causes me two problems

1). My Actor is no longer within my ViewModelScope
2). How do I call the ViewModel Dispatch method

To solve problem 2). I could pass the dispatch function into my Messenger class

How do I associate the actor with my ViewModelScope?

Does this entire approach have any value?

Upvotes: 6

Views: 552

Answers (1)

iamanbansal
iamanbansal

Reputation: 2742

You can pass the viewmodelScope in Messenger class and call the actor from that scope.

private val sendChannel: SendChannel<I> = viewModelScope.actor {
    for (message in channel) {
        dispatch(message) 
    }
}

also you can override the coroutineContext (which I suppose Sendable is a subclass of CoroutineScope)

  override val coroutineContext: CoroutineContext
    get() = viewModelScope.coroutineContext

Upvotes: 2

Related Questions