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.