Igo*_*yuk -1 android android-fragments kotlin android-viewmodel
我有一个包含一个活动和两个片段的应用程序,在第一个片段中,我应该能够将数据插入数据库,在第二个片段中,我应该能够在 recyclerView 中看到添加的项目。
所以我制作了数据库、我的 RecyclerView 适配器和 ViewModel,
现在的问题是我应该如何管理这一切?
我应该在活动中初始化 ViewModel 并从片段中以某种方式调用它以使用插入吗?
我应该在两个片段中初始化视图模型两次吗?
我的代码如下所示:
让我们假设我在我的 Activity 中初始化了 viewholder:
class MainActivity : AppCompatActivity() {
private val articoliViewModel: ArticoliViewModel by viewModels {
ArticoliViewModelFactory((application as ArticoliApplication).repository)
}
}
Run Code Online (Sandbox Code Playgroud)
然后我的 FirstFragments 方法,我应该使用 viewModel 将数据添加到数据库中,如下所示:
class FirstFragment : Fragment() {
private val articoliViewModel: ArticoliViewModel by activityViewModels()
private fun addArticolo(barcode: String, qta: Int) { // function which add should add items on click
// here i should be able to do something like this
articoliViewModel.insert(Articolo(barcode, qta))
}
}
Run Code Online (Sandbox Code Playgroud)
还有我的第二个片段
class SecondFragment : Fragment() {
private lateinit var recyclerView: RecyclerView
private val articoliViewModel: ArticoliViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView = view.findViewById(R.id.recyclerView)
val adapter = ArticoliListAdapter()
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(activity)
// HERE I SHOULD BE ABLE DO THIS
articoliViewModel.allWords.observe(viewLifecycleOwner) { articolo->
articolo.let { adapter.submitList(it) }
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
我的 ViewModel 看起来像这样:
class ArticoliViewModel(private val repository: ArticoliRepository): ViewModel() {
val articoli: LiveData<List<Articolo>> = repository.articoli.asLiveData()
fun insert(articolo: Articolo) = viewModelScope.launch {
repository.insert(articolo)
}
}
class ArticoliViewModelFactory(private val repository: ArticoliRepository): ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(ArticoliViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return ArticoliViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Run Code Online (Sandbox Code Playgroud)
多个片段是否应该共享一个 ViewModel 取决于它们是否显示相同的数据。如果它们显示相同的数据,我认为共享一个 ViewModel 通常是有意义的,这样在它们之间切换时就不必从存储库中提取数据,因此转换速度更快。如果它们中的任何一个也有大量的唯一数据,您可能会考虑将其分解为单独的 ViewModel,以便在不需要时不占用内存。
假设您使用的是共享 ViewModel,您可以使用至少两种不同的方式之一,具体取决于您喜欢的代码风格。封装和代码重复之间有一种小的权衡,尽管它并没有真正封装,因为它们正在查看同一个实例。所以就我个人而言,我更喜欢第二种方式。
by activityViewModels(),则 ViewModel 的范围将限定为 Activity,因此它们都将接收相同的实例。但是由于你的 ViewModel 需要自定义工厂,你必须在两个 Fragment 中都指定它,所以有一点代码重复:// In each Fragment:
private val articoliViewModel: ArticoliViewModel by activityViewModels {
ArticoliViewModelFactory((application as ArticoliApplication).repository)
}
Run Code Online (Sandbox Code Playgroud)
// In Activity: The same view model code you already showed in your Activity, but not private
// In Fragments:
private val articoliViewModel: ArticoliViewModel
get() = (activity as MainActivity).articoliViewModel
Run Code Online (Sandbox Code Playgroud)
或者为了避免代码重复,您可以为 Fragments 创建一个扩展属性,这样它们就不必有此代码重复:
val Fragment.articoliViewModel: ArticoliViewModel
get() = (activity as MainActivity).articoliViewModel
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
188 次 |
| 最近记录: |