Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 666
Hector Avatar asked Sep 04 '20 12:09

Hector


1 Answers

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
like image 112
iamanbansal Avatar answered Sep 28 '22 11:09

iamanbansal