Как передать параметр String в ViewModel в Compose? Я имею в виду строковую переменную, а не жестко закодированную или сохраненную в приложении. Мне нужно передать его как параметр. Это только для целей обучения, сейчас это строка, но завтра это может быть, например, собственный объект.
В лабораториях по коду объясняется, как передавать параметры, которые можно сгенерировать с помощью приложения, например:
companion object {
val factory : ViewModelProvider.Factory = viewModelFactory {
initializer {
MyViewModel(
MyApplication().container.repository
)
}
}
}
И позже используя эту переменную сопутствующего объекта следующим образом:
viewModel: MyViewModel = viewModel(factory = MyViewModel.factory)
Но они не объясняют, как передать простой строковый параметр. Как я могу адаптировать этот код для получения строки в качестве параметра и передачи ее при инициализации модели представления?
Я попробовал то, что предложил CommonsWare, и, очевидно, оно не компилируется, в объяснении чего-то не хватает. Как передать переменную myString? Я просто хочу преобразовать эту фабрику, чтобы получить строковую переменную, но не знаю, как этого добиться.
companion object {
val factory : ViewModelProvider.Factory = viewModelFactory {
initializer {
LoadingScreenViewModel(
myString
)
}
}
}
@CommonsWare Я не знаю, что я плохо объясняю. Я приложил к вопросу то, что вы предложили, переключив репо с помощью параметра String, и я не знаю, как его скомпилировать. Не могли бы вы мне помочь пожалуйста? Модель представления уже принимает строку в качестве параметра, но в сопутствующем объекте мне нужно передать эту строку, и я не знаю, как это сделать. С другой стороны, я не использую какую-либо структуру инверсии, это простой проект для изучения того, как передавать параметр в модель представления без использования сторонних библиотек, только с фабрикой и сопутствующим объектом.
Модели представления необходимо инициализировать с помощью фабрики, код, упомянутый в сопутствующем объекте, выполняет свою работу, но есть лучший способ создать viewModelFactory
.
Вот пример, в основном стандартный код, и скопируйте его в соответствии с вашими потребностями.
@Suppress("UNCHECKED_CAST")
class MyViewModelFactory(
private val someString1: String,
private val someString2: String,
private val someString3: String
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
// Change the ViewModel Class Name Below
if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
return MyViewModel(someString1, someString2, someString3) as T // Add the values to the MyViewModel constructor
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
companion object{
// Declaring a variable factory and initializing variables inside lambda function viewModelFactory.
val factory: ViewModelProvider.Factory = viewModelFactory {
initializer {
val someString = "some_string"
MyViewModel(someString)
}
}
// Declaring a function with constructors and with a similar approach as the above factory declaration.
fun factory(someString: String) : ViewModelProvider.Factory = viewModelFactory {
initializer {
MyViewModel(someString)
}
}
}
Привет, может быть, это можно сделать с помощью предложенного мной сопутствующего объекта? Можете ли вы предложить альтернативу, более похожую на ту, которую я опубликовал? Я имею в виду использование сопутствующего объекта. Пожалуйста, не удаляйте эту опцию, рассмотрите ее, если ее невозможно достичь с помощью сопутствующего объекта.
Конечно, это возможно, я обновлю ответ когда-нибудь.
Вариант 1. Используйте функцию
companion object {
fun factory(myString: String) : ViewModelProvider.Factory = viewModelFactory {
initializer {
LoadingScreenViewModel(
myString
)
}
}
}
Вариант 2: не используйте companion object
, а вместо этого инициализируйте фабрику в том месте, где она вам нужна.
val myString: String = TODO() // fill in logic to get your string value
val factory : ViewModelProvider.Factory = viewModelFactory {
initializer {
LoadingScreenViewModel(
myString
)
}
}
Вариант 3. Используйте предпочитаемую вами структуру инверсии зависимостей (Dagger/Hilt, Koin и т. д.) и избегайте создания собственной фабрики.
большое спасибо ! Компилируется, нет времени пробовать но думаю теперь все понял. Я постараюсь, чтобы это заработало в ближайшее время. Спасибо
Замените
MyApplication().container.repository
строковой переменной иMyViewModel()
примет параметрString
. Это заставляет меня думать, что я неправильно понимаю ваш вопрос. Не могли бы вы опубликовать минимально воспроизводимый пример, показывающий, что вы пробовали, и объясняющий, с какими проблемами вы столкнулись? Если вас беспокоит, чтоfactory
является собственностью наcompanion object
, это не является обязательным требованием. И если вас беспокоит, как это взаимодействует с вашей структурой инверсии зависимостей, какую из них вы используете?