【发布时间】:2021-07-20 03:33:31
【问题描述】:
我正在查看 Android room with a view 的教程,并尝试将他们的模型扩展为使用 ViewModels 到多个片段,但不确定如何。
我的应用程序
class myApplication : Application() {
companion object {
var database: myDatabase? = null
var repository: myRepository? = null
}
override fun onCreate() {
super.onCreate()
database = MyDatabase.getInstance(this)
repository = MyRepository(database!!.myDatabaseDao)
}
}
MyViewModel
class MyViewModel(private val repository: MyRepository) : ViewModel() {
val allWords: LiveData<List<Words>> = repository.allWords.asLiveData()
fun insert(word: Word) = viewModelScope.launch {
repository.insert(word)
}
}
class MyViewModelFactory(private val repository: MyRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return MyViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
HomeFragment
class HomeFragment : Fragment() {
private val myViewModel: MyViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
var rootView = inflater.inflate(R.layout.fragment_home, container, false)
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
myViewModel.allWords.observe(viewLifecycleOwner) { words ->
// Update the cached copy of the words in the adapter.
words.let { Log.d("fragment", it.toString()) }
}
}
}
我还有几个其他片段,希望它们与HomeFragment 共享相同的ViewModel。我尝试了许多不同的方法,例如使用
myViewModel = ViewModelProviders.of(activity!!).get(MyViewModel::class.java)
但他们都给我Caused by: java.lang.InstantiationException: java.lang.Class<com.example.tabtester.ViewModels.MyViewModel> has no zero argument constructor。我找不到任何 SO 帖子或文档来告诉我如何在 Kotlin 中提供构造函数。
从概念上讲,我找不到任何关于究竟发生了什么以及视图模型是如何构建的(以及由什么构建的)的描述。在 Room with a View 教程中,给出的示例在 MainActivity:
private val wordViewModel: WordViewModel by viewModels {
WordViewModelFactory((application as WordsApplication).repository)
}
这对我来说是有道理的;您正在使用 Factory 实例化要在 MainActivity 中使用的 ViewModel。但是对于如何在 Fragments 中使用 ViewModels 的任何描述,我看不到 ViewModel 是在哪里构造的。如果您有多个正在构建 ViewModel 的片段?如果我使用 Fragments 那么这是否意味着我还需要一个 Activity 来构造 ViewModel,然后以某种方式在 Fragments 之间共享?
如果有任何帮助或文档可以更清楚地解释这一点,我们将不胜感激。
【问题讨论】:
-
by activityViewModels()将工厂作为可选参数。为什么不将自定义工厂传递给它? -
我试了一下,抛出了
java.lang.IllegalArgumentException: Cannot add the same observer with different lifecycles。 -
听起来你可以让你的共享 ViewModel 正常工作(它现在正在成功创建你的 ViewModel)。
-
它编译并创建了一个 ViewModel,但不清楚它是否工作 - 我不确定如何实际观察我的数据并测试它是否是跨片段的共享视图模型实例。
-
我修复了观察者错误,如果我按照您的建议添加
private val myViewModel: MyViewModel by activityViewModels() {MyViewModelFactory(MyApplication.repository!!)},它看起来可能有效!但是,这是否意味着如果我将这一行添加到每个Fragment类中,它将使用ViewModel的共享实例而不是创建新实例?
标签: android kotlin android-fragments mvvm