从 RecyclerView 适配器中访问 ViewModel 函数
Accessing ViewModel functions from within a RecyclerView adapter
我是 Android 开发的新手,正在研究一些基本的 Android 应用程序以了解更多信息。我想尽早学习 MVMM 架构最佳实践,并且很好奇如何最好地解决以下任务:在一个简单的列表应用程序中,我的 ViewModel 包含列表数据以及用于添加和删除数据的函数(我从 Android 开发者教程)。
RecyclerView 在Fragment 中显示列表数据。我将 RecyclerView 适配器用作用户与之交互的 UI 列表项和适当的 ViewModel 函数调用之间的 'bridge'。最初,我使用接口实现了它,但这不允许我将对 ViewModel 的引用作为构造函数参数传递,所以现在我使用内部 class ,如许多关于在 RecyclerView 适配器中设置 ClickListeners 的 SO 帖子中所述:
class MainAdapter(
val viewModel: ListViewModel, // reference to entire ViewModel just to access functions therein
private var list: LiveData<MutableList<String>>, // stored in ViewModel
private val listener: OnItemClickListener // defined in inner class below
) :
RecyclerView.Adapter<MainAdapter.ViewHolder>() {
inner class OnItemClickListener(viewModel: ListViewModel) {
fun onClick(mainItem: String) {
// (TODO) navigate to DetailListFragment and display appropriate list
}
fun onLongClick(mainItem: String) {
// contact viewModel to delete this item
viewModel.deleteItemMainList(mainItem)
}
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.list_item_text.text = list.value?.elementAt(position)
holder.itemView.setOnClickListener(View.OnClickListener {
listener.onClick(list.value?.elementAt(position)!!)
})
holder.itemView.setOnClickListener(View.OnClickListener {
listener.onLongClick(list.value?.elementAt(position)!!)
})
}
override fun getItemCount(): Int {
return list.value?.size ?: 0
}
}
有没有比只传递对我的整个 ViewModel 的引用以访问其中的函数更好的解决方案?
如果这是最合适的解决方案,我在片段 class 中初始化适配器时遇到错误:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
// Error:
// Constructor of inner class OnItemClickListener can be called only with receiver of containing class:
adapter = MainAdapter(viewModel ,viewModel.mainList, MainAdapter.OnItemClickListener(viewModel) )
main_list_view.adapter = adapter
main_list_view.layoutManager = LinearLayoutManager(requireContext())
recyclerView = binding.mainListView
}
我的 ViewModel 包含数据和函数:
class ListViewModel : ViewModel() {
private val _mainList = MutableLiveData<MutableList<String>>()
val mainList: LiveData<MutableList<String>> = _mainList
init {
_mainList.value = arrayListOf()
_detailList.value = arrayListOf(arrayListOf())
}
fun addItemMainList(item: String) {
if (_mainList.value?.contains(item) == false) {
_mainList.value?.add(item)
_mainList.value = _mainList.value
}
}
fun deleteItemMainList(item: String) {
_mainList.value?.remove(item)
_mainList.value = _mainList.value
}
}
最后,我意识到以这种方式存储列表数据不是持久化的,Room 是持久化数据的合适方式,但首先我想了解如何使用 MVMM 最佳实践正确连接 UI 事件和我的 ViewModel .
到目前为止探索的参考样本:
。来自您共享的资源之一的评论回答了您的问题。只需传递必要的内容(例如列表),然后在您的 recyclerView 中创建接口以在调用 activity 或 Fragment 中调用。然后从那里访问您的 Viewmodel。
可以将 ViewModel 传递给 recyclerView 吗?..我的意思是回收器视图将绑定到片段的生命周期或者 activity 你从回收器视图调用它所以没关系但不是一个好的做法
我是 Android 开发的新手,正在研究一些基本的 Android 应用程序以了解更多信息。我想尽早学习 MVMM 架构最佳实践,并且很好奇如何最好地解决以下任务:在一个简单的列表应用程序中,我的 ViewModel 包含列表数据以及用于添加和删除数据的函数(我从 Android 开发者教程)。
RecyclerView 在Fragment 中显示列表数据。我将 RecyclerView 适配器用作用户与之交互的 UI 列表项和适当的 ViewModel 函数调用之间的 'bridge'。最初,我使用接口实现了它,但这不允许我将对 ViewModel 的引用作为构造函数参数传递,所以现在我使用内部 class ,如许多关于在 RecyclerView 适配器中设置 ClickListeners 的 SO 帖子中所述:
class MainAdapter(
val viewModel: ListViewModel, // reference to entire ViewModel just to access functions therein
private var list: LiveData<MutableList<String>>, // stored in ViewModel
private val listener: OnItemClickListener // defined in inner class below
) :
RecyclerView.Adapter<MainAdapter.ViewHolder>() {
inner class OnItemClickListener(viewModel: ListViewModel) {
fun onClick(mainItem: String) {
// (TODO) navigate to DetailListFragment and display appropriate list
}
fun onLongClick(mainItem: String) {
// contact viewModel to delete this item
viewModel.deleteItemMainList(mainItem)
}
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.list_item_text.text = list.value?.elementAt(position)
holder.itemView.setOnClickListener(View.OnClickListener {
listener.onClick(list.value?.elementAt(position)!!)
})
holder.itemView.setOnClickListener(View.OnClickListener {
listener.onLongClick(list.value?.elementAt(position)!!)
})
}
override fun getItemCount(): Int {
return list.value?.size ?: 0
}
}
有没有比只传递对我的整个 ViewModel 的引用以访问其中的函数更好的解决方案?
如果这是最合适的解决方案,我在片段 class 中初始化适配器时遇到错误:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
// Error:
// Constructor of inner class OnItemClickListener can be called only with receiver of containing class:
adapter = MainAdapter(viewModel ,viewModel.mainList, MainAdapter.OnItemClickListener(viewModel) )
main_list_view.adapter = adapter
main_list_view.layoutManager = LinearLayoutManager(requireContext())
recyclerView = binding.mainListView
}
我的 ViewModel 包含数据和函数:
class ListViewModel : ViewModel() {
private val _mainList = MutableLiveData<MutableList<String>>()
val mainList: LiveData<MutableList<String>> = _mainList
init {
_mainList.value = arrayListOf()
_detailList.value = arrayListOf(arrayListOf())
}
fun addItemMainList(item: String) {
if (_mainList.value?.contains(item) == false) {
_mainList.value?.add(item)
_mainList.value = _mainList.value
}
}
fun deleteItemMainList(item: String) {
_mainList.value?.remove(item)
_mainList.value = _mainList.value
}
}
最后,我意识到以这种方式存储列表数据不是持久化的,Room 是持久化数据的合适方式,但首先我想了解如何使用 MVMM 最佳实践正确连接 UI 事件和我的 ViewModel .
到目前为止探索的参考样本:
可以将 ViewModel 传递给 recyclerView 吗?..我的意思是回收器视图将绑定到片段的生命周期或者 activity 你从回收器视图调用它所以没关系但不是一个好的做法