DEV Community

Discussion on: Maximizing Code Sharing between Android and iOS with Kotlin Multiplatform

Collapse
 
kuuurt profile image
Kurt Renzo Acosta • Edited

The disadvantage in usage the snippet above though would be for testing.

Since CommonFlow isn't a Flow in commonMain, unit tests in commonTest turn into red. For that reason, I still used the CFlow but just used asLiveData() in Android

Thread Thread
 
qrezet profile image
qrezet • Edited

Aha! I see, it is because you want to make the Android ViewModel and iOS "ViewModel" seem to be just the same.

Hmmm... In my opinion, and this is purely my opinion, I would keep Android ViewModel and whatever iOS "ViewModel" seperate from each other. They are platform specific concepts and I don't think its good idea to mix them as one. I would rather therefore move all logic outside these "ViewModels" which would make these "ViewModels" just "wrapper" or "wiring class".

This would make me safe from any changes these platform specific constructs. :) But then again just my pure opinion. I guess it is at this point that developers tend to argue. Until what layer should be shared?

Thread Thread
 
kuuurt profile image
Kurt Renzo Acosta • Edited

Not really. The ViewModel is already different based on the platform. You can check BaseViewModel wherein on Android, it uses Architecture Components, and on iOS, it's just a custom implementation.

I beg to differ, the ViewModel can be shared. Ideally, it shouldn't have a dependency on the platform's framework. You have the view (aka Fragment / Activity / ViewController) for that. For example:

class LoginViewModel(private val loginUseCase: Login) : BaseViewModel() {
    private val _loginState: ConflatedBroadcastChannel<UiState>()
    val loginState = _loginState.wrap() 

    fun login(username: String, password: String) {
        clientScope.launch {
            _loginState.offer(UiState.Loading)
            loginUseCase(username, password)
            _loginState.offer(UiState.Complete)
        }
    }
}

There's no platform-specific implementation. It's just pure logic.

The watch function on the CFlow class is just sort of an extension for iOS which you can choose to use or not in Android. iOS cannot get suspend functions which is why we have to resort to some workaround for now.

You can choose to use the expect/actual implementation for CommonFlow and use the normal Flow in Android and use CFlow for iOS however this makes you unable to test it in commonTest since this sourceSet will use commonMain and in the declaration, it's not a Flow and you can't let and expect declaration inherit from something so you have to create both of the tests in androidTest and iosTest

I think exposing a function doesn't hurt. It's not like we changed the whole implementation. We just added something for it to be used on the other side.

But that's my opinion and what's worked for me so you can still go ahead and try your implementation out and see if it works for you. :)

TL;DR Add a watch function so we can use Flow on iOS vs. Write them separately on each platform. I go for using watch