![](/img/trans.png)
[英]Android Google maps fragment in RecyclerView.ViewHolder
[英]Won't notifyDataSetChanged() launch init{ } in RecyclerView.ViewHolder in Android Studio?
我正在使用 ListAdapter 学习 RecyclerView。
1:我发现init{ }
setControl()
在我运行notifyDataSetChanged()
后没有启动,为什么?
2:我应该将什么代码放在init{ }
? 我应该将什么代码放在fun bind(aMVoice: MVoice{ }
?
代码
class VoiceAdapters (private val aHomeViewModel: HomeViewModel):
ListAdapter<MVoice, VoiceAdapters.VoiceViewHolder>(MVoiceDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VoiceViewHolder {
return VoiceViewHolder(
LayoutVoiceItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
override fun onBindViewHolder(holder: VoiceViewHolder, position: Int) {
val aMVoice = getItem(position)
holder.bind(aMVoice)
}
inner class VoiceViewHolder (private val binding: LayoutVoiceItemBinding):
RecyclerView.ViewHolder(binding.root) {
init {
setControl()
}
fun bind(aMVoice: MVoice) {
binding.amVoice = aMVoice
binding.executePendingBindings()
}
fun setControl(){
binding.aHomeViewModel = aHomeViewModel
binding.chSelect.setOnCheckedChangeListener{ _, isChecked ->
binding.amVoice?.let {
...
}
}
...
}
}
}
新增内容:
致 ADM:非常感谢!
A:为什么将 ViewModel 传递给适配器不是一个好主意?
B: 我怎样才能改用接口? 你能告诉我一些示例代码吗?
BTW,下面RecyclerView的item布局需要使用ViewModel aHomeViewModel
来控制CheckBox chSelect
是否显示。 我将在片段中设置aHomeViewModel.displayCheckBox
的值。
layout_voice_item.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable name="aMVoice"
type="info.dodata.voicerecorder.model.MVoice" />
<variable name="aHomeViewModel"
type="info.dodata.voicerecorder.viewcontrol.HomeViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<CheckBox
android:id="@+id/chSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{aHomeViewModel.displayCheckBox? View.VISIBLE: View.GONE}"
android:text="" />
<TextView
android:id="@+id/voiceID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{Integer.toString(aMVoice.id)}" />
</LinearLayout>
</layout>
RecyclerView
多次重用同一个ViewHolder
这就是为什么构造函数没有被调用。 因此,应该为所有项目完成的任何绑定 Stuff 都应该写在onBindViewHolder
。
在调用notifyDataSetChanged
onBindViewHolder
时,屏幕上可见的位置将被调用,并且相同的ViewHolder
将被重用(这取决于)。 但是这里的事情是不会每次都创建一个新的ViewHolder
所以你不能用我们的构造函数来进行这样的操作。
我应该将什么代码放在 init{} 中? 我应该将什么代码放在 fun bind(aMVoice: MVoice{ } ?
在init
您可以找到视图并设置动作侦听器。 在bind
你为每个项目做一些事情,即将数据设置到视图中。
另一方面,您不应该将ViewModel
传递给适配器,这不是一个好主意,而是使用interface
。
为什么不将 ViewModel 传递给 Adapter最终ViewModel
只是一个类,因此您可以传递它并且不会给出任何错误。 我现在能想到不这样做的原因如下:-
通过传递ViewModel
将适配器与单个ViewModel
紧密耦合,即ViewModel
为 Activity 或片段。 现在你不能在任何其他地方重用这个适配器
同样,拥有ViewModel
的全部意义在于观察通常不会发生在 Adapter 内部的数据流。
记住一件事ViewModel
(LiveData) 不是回调接口的替代品。 所以你应该在这里使用回调接口,因为你在这里不需要生命周期组件。
因此,不要直接将ViewModel
传递给适配器,而是将数据集传递给适配器如果您需要在操作(单击、长按)上通知Activity
或Fragment
,请使用接口。
init
将在创建ViewHolder
时调用一次。 这就是为什么RecyclerView
有 recycle 一词的原因。 它将重用它的对象。 因此init
在ViewHolder
的生命周期中只会被调用一次。 当内容可见(或接近可见)时,将调用bind
。 在bind
调用setControl
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.