Home > database >  Error when creating ViewModel in Jetpack Compose
Error when creating ViewModel in Jetpack Compose

Time:01-04

When I try to create the ViewModel via viewModel(), I receive the following error:

FATAL EXCEPTION: main
Process: com.github.profit, PID: 23095
java.lang.ClassCastException: java.lang.Object cannot be cast to androidx.lifecycle.ViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:201)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:322)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:304)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:175)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:138)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
at androidx.lifecycle.viewmodel.compose.ViewModelKt.get(ViewModel.kt:215)
at androidx.lifecycle.viewmodel.compose.ViewModelKt.viewModel(ViewModel.kt:156)
at com.github.profit.MainActivityKt.ProductInfo(MainActivity.kt:136)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:31)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:30)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.material.SurfaceKt$Surface$6.invoke(Surface.kt:268)
at androidx.compose.material.SurfaceKt$Surface$6.invoke(Surface.kt:255)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.material.SurfaceKt.Surface-F-jzlyU(Surface.kt:252)
at androidx.compose.material.SurfaceKt.Surface-F-jzlyU(Surface.kt:110)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-2$1.invoke(MainActivity.kt:27)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-2$1.invoke(MainActivity.kt:25)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.material.MaterialTheme_androidKt.PlatformMaterialTheme(MaterialTheme.android.kt:23)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1$1.invoke(MaterialTheme.kt:82)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1$1.invoke(MaterialTheme.kt:81)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.material.TextKt.ProvideTextStyle(Text.kt:265)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:81)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:80)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.material.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:72)
at com.github.profit.ui.theme.ThemeKt.ProfitTheme(Theme.kt:38)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-3$1.invoke(MainActivity.kt:25)
at com.github.profit.ComposableSingletons$MainActivityKt$lambda-3$1.invoke(MainActivity.kt:24)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)

My application looks like this:

MainActivity

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ProfitTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    ProductInfo()
                }
            }
        }
    }
}

ProductInfo

@Composable
fun ProductInfo() {
    val viewModel: ProductsViewModel by viewModel()

    Column {
        TextField(
            value = viewModel.product1Price,
            onValueChange = {
                viewModel.product1Price = it
            },
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
            label = { Text(text = "Price") },
            placeholder = { Text(text = "Price in Ft") },
        )
        // ...
    }
}

ProductsViewModel

class ProductsViewModel: ViewModel() {
    private val _product1Price = mutableStateOf(0U)
    private val _product1Quantity = mutableStateOf(0U)
    private val _product2Price = mutableStateOf(0U)
    private val _product2Quantity = mutableStateOf(0U)

    var product1Price: String
        get() = _product1Price.value.toString()
        set(value) = setField(_product1Price, value)

    // ...
}

My project build.gradle

buildscript {
    ext {
        compose_ui_version = '1.1.1'
        lifecycle_version = '2.5.1'
    }
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id 'com.android.application' version '7.3.1' apply false
    id 'com.android.library' version '7.3.1' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}

The app's build.gradle:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    namespace 'com.github.profit'
    compileSdk 32

    defaultConfig {
        applicationId "com.github.profit"
        minSdk 22
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary true
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion '1.1.1'
    }
    packagingOptions {
        resources {
            excludes  = '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
}

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.activity:activity-compose:1.3.1'
    implementation "androidx.compose.ui:ui:$compose_ui_version"
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
    implementation 'androidx.compose.material:material:1.1.1'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.4'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
    debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
    debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"
}

CodePudding user response:

You can create a view model in compose like like,

val viewModel = viewModel<ProductsViewModel>()

or

val viewModel: ProductsViewModel = viewModel()

For more info refer this codelab.

  • Related