Androidx.lifecycle:lifecycle.viewmodel.compose против androidx.hilt:hilt.navigation.composeAndroid

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Androidx.lifecycle:lifecycle.viewmodel.compose против androidx.hilt:hilt.navigation.compose

Сообщение Anonymous »

Следуя документации Android из разных мест:

[*]Используйте Hilt с другими библиотеками Jetpack: внедрите объекты ViewModel с помощью Hilt
[*]Compose и другие библиотеки: ViewModel
[*]Compose и другие библиотеки: Hilt
[*]Внедрение зависимостей с помощью Hilt

А это StackOverflow ответ:
Как добавить зависимости Hilt к файлу «libs.versions.toml» в студии Android
Я пытался использовать androidx.lifecycle:lifecycle.viewmodel.compose, но я все еще получаю следующую ошибку, которую не могу понять даже через несколько дней:

Код: Выделить всё

FATAL EXCEPTION: main (Ask Gemini)
Process: com.app, PID: 5391
java.lang.RuntimeException: Cannot create an instance of class com.app.ui.login.LoginViewModel
at androidx.lifecycle.viewmodel.internal.JvmViewModelProviders.createViewModel(JvmViewModelProviders.kt:40)
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.android.kt:193)
...
Ниже представлена ​​моя работа по созданию очень простой страницы входа в систему:
libs.version.toml

Код: Выделить всё

[versions]
agp = "8.7.3"
kotlin = "2.0.0"
coreKtx = "1.10.1"
...
lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.8.0"
composeBom = "2024.04.01"
#navigation
navVersion = "2.8.5"
jsonSerializationVersion = "1.7.3"
#hilt
kspVersion = "2.0.0-1.0.24"
hiltVersion = "2.51.1"
lifecycleViewmodelComposeVersion = "2.8.7"

[libraries]
#default generated
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
...
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
...
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
# password visibility icon
androidx-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended"}
#----
#----
#navigation
androidx-navigation-compose = {group = "androidx.navigation", name = "navigation-compose", version.ref = "navVersion"}
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "jsonSerializationVersion"}
#----
#hilt
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hiltVersion"}
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hiltVersion"}
androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelComposeVersion"}

[plugins]
#default generated
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin"  }
#----
#navigation
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin"}
#hilt
kotlinAndroidKsp = { id = "com.google.devtools.ksp", version.ref = "kspVersion"}
hiltAndroid = { id = "com.google.dagger.hilt.android", version.ref = "hiltVersion"}
build.gradle.kts(App)

Код: Выделить всё

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
//generated
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
//----
//hilt
alias(libs.plugins.hiltAndroid) apply false
alias(libs.plugins.kotlinAndroidKsp) apply false
}
build.gradle.kts(:app)

Код: Выделить всё

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
//navigation
alias(libs.plugins.kotlin.serialization)
//hilt
alias(libs.plugins.hiltAndroid)
alias(libs.plugins.kotlinAndroidKsp)
}

android {
namespace = "com.app"
compileSdk = 34

defaultConfig {
applicationId = "com.app"
minSdk = 33
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
}

dependencies {

//default generated
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
// password visibility icon
implementation(libs.androidx.material.icons.extended)
//----
//----
//navigation
implementation(libs.androidx.navigation.compose)
implementation(libs.kotlinx.serialization.json)
//----
//hilt
implementation(libs.hilt.android)
ksp(libs.hilt.compiler)
implementation(libs.androidx.lifecycle.viewmodel.compose)
//----
}
AndroidManifest.xml

Код: Выделить всё





Main(
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}

@Composable
fun Main(modifier: Modifier = Modifier) {
val navController = rememberNavController()
NavHost(navController, startDestination = Login) {
composable {
Login(
modifier = modifier,
onRegisterClick = { Log.d(TAG, "Nav to register success")/*navController.navigate(route = Register)*/ },
onLoginSuccess = { Log.d(TAG, "Login Success") }
)
}
}
}
Login.kt

Код: Выделить всё

import androidx.compose.foundation.layout.Arrangement
...
import androidx.lifecycle.viewmodel.compose.viewModel
import com.app.ui.shared.PasswordField
import com.app.ui.shared.UsernameField

@Composable
fun Login(
modifier: Modifier = Modifier,
vm: LoginViewModel = viewModel(),
onRegisterClick: () -> Unit = {},
onLoginSuccess: () -> Unit = {}
) {
//Also tried: val vm:LoginViewModel by viewModel()
val uiState by vm.uiState.collectAsStateWithLifecycle()
val kbController = LocalSoftwareKeyboardController.current

Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
val textFieldModifier = Modifier.fillMaxWidth().padding(16.dp,4.dp)

UsernameField(uiState.username, vm::onUsernameChange, textFieldModifier)
PasswordField(uiState.password, vm::onPasswordChange, textFieldModifier)

Button(
onClick = {
kbController?.hide()
vm.onLoginClick(onLoginSuccess = onLoginSuccess)
},
modifier = Modifier.fillMaxWidth().padding(16.dp,8.dp)
) {
Text(text = "Sign In", fontSize = 16.sp)
}
...
}

}
LoginViewModel.kt

Код: Выделить всё

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.app.domain.BasicAuthUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
...

@HiltViewModel
class LoginViewModel @Inject constructor(
private val basicAuthUseCase: BasicAuthUseCase
): ViewModel() {

private val _uiState = MutableStateFlow(LoginState())
val uiState: StateFlow = _uiState.asStateFlow()

fun onUsernameChange(username: String) =
_uiState.update { it.copy(username = username) }
fun onPasswordChange(password: String) =
_uiState.update { it.copy(password = password) }
fun onLoginClick(onLoginSuccess: () ->  Unit) {
...
}
fun hideAfterDelay(duration: Long){
...
}

}
HiltBindings.kt

Код: Выделить всё

import com.app.domain.BasicAuthUseCase
import com.app.domain.BasicAuthUseCaseImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
abstract class HiltBindings {
@Binds
abstract fun bindBasicAuthUseCase(impl: BasicAuthUseCaseImpl): BasicAuthUseCase
}
BasicAuthUseCase.kt

Код: Выделить всё

interface BasicAuthUseCase {
suspend fun verifyUser(username: String, password: String): Boolean
suspend fun isUsernameExist(username: String): Boolean
suspend fun registerUser(username: String,password: String): Boolean
}
Вспоминая несколько лет назад, когда мне удалось заставить это работать, я внес следующие изменения и сумел заставить это работать, заменив androidx.lifecycle:lifecycle.viewmodel.compose на androidx .hilt:hilt.navigation.compose:
libs.version.toml

Код: Выделить всё

[versions]
...
#hilt
kspVersion = "2.0.0-1.0.24"
hiltVersion = "2.51.1"
#lifecycleViewmodelComposeVersion = "2.8.7"
hiltNavigationComposeVersion = "1.2.0"

[libraries]
...
#hilt
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hiltVersion"}
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hiltVersion"}
#androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelComposeVersion"}
androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationComposeVersion"}

[plugins]
...
build.gradle.kts(:app)

Код: Выделить всё

...

dependencies {

...
//hilt
implementation(libs.hilt.android)
ksp(libs.hilt.compiler)

//    implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.hilt.navigation.compose)
//----
}
Login.kt

Код: Выделить всё

import androidx.compose.foundation.layout.Arrangement
...
import androidx.hilt.navigation.compose.hiltViewModel
import com.app.ui.shared.PasswordField
import com.app.ui.shared.UsernameField

@Composable
fun Login(
modifier: Modifier = Modifier,
vm: LoginViewModel = hiltViewModel(),
onRegisterClick: () -> Unit = {},
onLoginSuccess: () -> Unit = {}
) {
...
}
Могу ли я получить помощь, чтобы понять, что я сделал не так с androidx.lifecycle:lifecycle.viewmodel.compose? Предполагается, что это рекомендуемое решение (Compose и другие библиотеки), но мне не удалось заставить его работать.

Подробнее здесь: https://stackoverflow.com/questions/792 ... navigation
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Androidx.lifecycle:lifecycle.viewmodel.compose против androidx.hilt:hilt.navigation.compose
    Anonymous » » в форуме Android
    0 Ответы
    55 Просмотры
    Последнее сообщение Anonymous
  • Дублирующийся класс androidx.lifecycle.ViewModelLazy найден в модулях lifecycle-viewmodel-2.5.0-runtime
    Гость » » в форуме Android
    0 Ответы
    69 Просмотры
    Последнее сообщение Гость
  • (Java) Обновление androidx.lifecycle:lifecycle-viewmodel
    Anonymous » » в форуме Android
    0 Ответы
    78 Просмотры
    Последнее сообщение Anonymous
  • Не удалось разрешить: androidx.lifecycle:lifecycle-extensions-ktx:2.0.0-alpha1.
    Гость » » в форуме Android
    0 Ответы
    74 Просмотры
    Последнее сообщение Гость
  • Неопределенные символы для архитектуры ARM64: "_Kfun: androidx.lifecycle.viewmodel.compose
    Anonymous » » в форуме Android
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Android»