rickclephas / KMP-ObservableViewModel

Library to use AndroidX/Kotlin ViewModels with SwiftUI
MIT License
569 stars 29 forks source link

Supertypes of the following classes cannot be resolved #46

Closed amadeuszblanik closed 1 year ago

amadeuszblanik commented 1 year ago

I cannot implement ViewModel on Android. iOS works fine. Tried it on ALPHA-12 and ALPHA-10.

Error

Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
    class me.blanik.sample.SignInViewModel, unresolved supertypes: com.rickclephas.kmm.viewmodel.KMMViewModel
Adding -Xextended-compiler-checks argument might provide additional information.

Shared gradle

plugins {
    kotlin("multiplatform")
    kotlin("native.cocoapods")
    id("com.android.library")
    id("com.google.devtools.ksp") version "1.9.0-1.0.11"
    id("com.rickclephas.kmp.nativecoroutines") version "1.0.0-ALPHA-13"
    kotlin("plugin.serialization") version "1.7.20"
}

@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class)
kotlin {
    androidTarget()
    jvmToolchain(11)

    iosX64()
    iosArm64()
    iosSimulatorArm64()

    cocoapods {
        summary = "Some description for the Shared Module"
        homepage = "Link to the Shared Module homepage"
        version = "1.0"
        ios.deploymentTarget = "14.1"
        podfile = project.file("../iosApp/Podfile")
        framework {
            baseName = "shared"
        }
    }

    sourceSets {
        val multiplatformSettingsVersion = "1.0.0"
        val kmmViewModelVersion = "1.0.0-ALPHA-12"

        all {
            languageSettings.optIn("kotlin.experimental.ExperimentalObjCName")
        }

        val commonMain by getting {
            dependencies {
                implementation("com.russhwolf:multiplatform-settings-no-arg:$multiplatformSettingsVersion")
                implementation("com.russhwolf:multiplatform-settings-serialization:$multiplatformSettingsVersion")
                implementation("com.russhwolf:multiplatform-settings-coroutines:$multiplatformSettingsVersion")
                implementation("com.rickclephas.kmm:kmm-viewmodel-core:$kmmViewModelVersion")
            }
        }

        val commonTest by getting {
            dependencies {
                implementation(kotlin("test"))
            }
        }

        val androidMain by getting {
            dependencies {
                implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
            }
        }
        val androidUnitTest by getting
        val iosX64Main by getting
        val iosArm64Main by getting
        val iosSimulatorArm64Main by getting
        val iosMain by creating {
            dependsOn(commonMain)
            iosX64Main.dependsOn(this)
            iosArm64Main.dependsOn(this)
            iosSimulatorArm64Main.dependsOn(this)

            dependencies {
            }
        }
        val iosX64Test by getting
        val iosArm64Test by getting
        val iosSimulatorArm64Test by getting
        val iosTest by creating {
            dependsOn(commonTest)
            iosX64Test.dependsOn(this)
            iosArm64Test.dependsOn(this)
            iosSimulatorArm64Test.dependsOn(this)
        }
    }
}

android {
    namespace = "me.blanik.sample"
    compileSdk = 33
    defaultConfig {
        minSdk = 28
    }

    // @TODO: Remove workaround for https://issuetracker.google.com/issues/260059413
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
}

Android Implementation:

package me.blanik.sample.android

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import me.blanik.sample.Greeting
import me.blanik.sample.SignInViewModel

class MainActivity : ComponentActivity() {
    private val viewModel: SignInViewModel() by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApplicationTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    GreetingView(Greeting().greet())
                    GreetingView(viewModel.email.value)
                }
            }
        }
    }
}

@Composable
fun GreetingView(text: String) {
    Text(text = text)
}

@Preview
@Composable
fun DefaultPreview() {
    MyApplicationTheme {
        GreetingView("Hello, Android!")
    }
}

Kotlin Shared:

package me.blanik.sample

import com.rickclephas.kmm.viewmodel.*
import kotlinx.coroutines.flow.*

open class SignInViewModel: KMMViewModel() {
    private val _email = MutableStateFlow(viewModelScope, "")
    private val _password = MutableStateFlow(viewModelScope, "")

    val email = _email.asStateFlow()
    val password = _password.asStateFlow()

    fun setEmail(email: String) {
        _email.value = email
    }

    fun setPassword(password: String) {
        _password.value = password
    }
}
amadeuszblanik commented 1 year ago

Added implementation("com.rickclephas.kmm:kmm-viewmodel-core:1.0.0-ALPHA-12") to my android Gradle and it worked 🎉

rickclephas commented 1 year ago

You might want to make the dependency an api dependency in your shared module:

- implementation("com.rickclephas.kmm:kmm-viewmodel-core:$kmmViewModelVersion")
+ api("com.rickclephas.kmm:kmm-viewmodel-core:$kmmViewModelVersion")

In which case the dependency isn't needed in the Android module.

amadeuszblanik commented 1 year ago

You might want to make the dependency an api dependency in your shared module:

- implementation("com.rickclephas.kmm:kmm-viewmodel-core:$kmmViewModelVersion")
+ api("com.rickclephas.kmm:kmm-viewmodel-core:$kmmViewModelVersion")

In which case the dependency isn't needed in the Android module.

This works perfectly for me! Your library is a beautifully crafted piece of work. I hope it continues to grow. I've created some samples using ktor.io. If they're helpful to you, please feel free to use them: https://github.com/amadeuszblanik/kmm-samples/tree/main.