Как передать строковый параметр в модель представления в составлении?

Как передать параметр 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
                )
            }
        }
    }

Замените MyApplication().container.repository строковой переменной и MyViewModel() примет параметр String. Это заставляет меня думать, что я неправильно понимаю ваш вопрос. Не могли бы вы опубликовать минимально воспроизводимый пример, показывающий, что вы пробовали, и объясняющий, с какими проблемами вы столкнулись? Если вас беспокоит, что factory является собственностью на companion object, это не является обязательным требованием. И если вас беспокоит, как это взаимодействует с вашей структурой инверсии зависимостей, какую из них вы используете?

CommonsWare 21.06.2024 16:16

@CommonsWare Я не знаю, что я плохо объясняю. Я приложил к вопросу то, что вы предложили, переключив репо с помощью параметра String, и я не знаю, как его скомпилировать. Не могли бы вы мне помочь пожалуйста? Модель представления уже принимает строку в качестве параметра, но в сопутствующем объекте мне нужно передать эту строку, и я не знаю, как это сделать. С другой стороны, я не использую какую-либо структуру инверсии, это простой проект для изучения того, как передавать параметр в модель представления без использования сторонних библиотек, только с фабрикой и сопутствующим объектом.

NullPointerException 21.06.2024 17:38
1
2
93
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Модели представления необходимо инициализировать с помощью фабрики, код, упомянутый в сопутствующем объекте, выполняет свою работу, но есть лучший способ создать viewModelFactory. Вот пример, в основном стандартный код, и скопируйте его в соответствии с вашими потребностями.

  1. Создав отдельный класс 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")
    }
}
  1. Использование сопутствующего объекта в ViewModel
   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. Внедрение зависимости

Привет, может быть, это можно сделать с помощью предложенного мной сопутствующего объекта? Можете ли вы предложить альтернативу, более похожую на ту, которую я опубликовал? Я имею в виду использование сопутствующего объекта. Пожалуйста, не удаляйте эту опцию, рассмотрите ее, если ее невозможно достичь с помощью сопутствующего объекта.

NullPointerException 21.06.2024 17:40

Конечно, это возможно, я обновлю ответ когда-нибудь.

Dr. Sa.M. 21.06.2024 19:37
Ответ принят как подходящий

Вариант 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 и т. д.) и избегайте создания собственной фабрики.

большое спасибо ! Компилируется, нет времени пробовать но думаю теперь все понял. Я постараюсь, чтобы это заработало в ближайшее время. Спасибо

NullPointerException 21.06.2024 18:16

Другие вопросы по теме