android - 不会 notifyDataSetChanged() 在 Android Studio 的 RecyclerView.ViewHolder 中启动 init{ }?
问题描述
我正在使用 ListAdapter 学习 RecyclerView。
1:我发现setControl()
在init{ }
我运行后没有启动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 传递给 adapter 不是一个好主意?
B: 我怎样才能使用界面呢?你能给我看一些示例代码吗?
BTW,下面 RecyclerView 的 item 布局需要使用 ViewModelaHomeViewModel
来控制 CheckBoxchSelect
是否显示。我将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
多次重复使用相同的东西,这就是构造函数不被调用的原因。所以任何应该为所有项目做的绑定东西都应该写在里面onBindViewHolder
。
调用notifyDataSetChanged
onBindViewHolder
时将调用屏幕上可见的位置,并且ViewHolder
将重复使用相同的位置(这取决于)。但是这里的事情是ViewHolder
每次都不会创建一个新的,所以你不能使用构造函数进行这样的操作。
我应该在 init{ } 中放置什么代码?我应该将什么代码放在 fun bind(aMVoice: MVoice{ } 中?
在里面init
你可以找到视图并设置动作监听器。你在里面bind
为每个项目做这些事情,即为视图设置数据。
另一方面,您不应该将 a 传递ViewModel
给不是一个好主意的适配器,interface
而是使用 an 。
为什么你不将 ViewModel 传递给 Adapter
Well 最终ViewModel
只是一个类,所以你可以传递它并且它不会给出任何错误。我现在能想到的不这样做的原因如下:-
通过传递
ViewModel
yo 将适配器紧密耦合到单个ViewModel
,即轮流 Activity 或片段。现在你不能在任何其他地方重用这个适配器还有一个重点
ViewModel
是观察通常不会在适配器内部发生的数据流。
记住一件事ViewModel
(LiveData)不是回调接口的替代品。所以你应该在这里使用回调接口因为你在这里不需要生命周期组件。
因此,不要ViewModel
直接将数据集传递给适配器,如果您需要通知Activity
操作Fragment
(单击、长按),请使用接口。
推荐阅读
- ios - 了解 Apple 远程收据
- javascript - 验证完成后,Nestjs 将函数应用于每个控制器函数/路由
- vulkan - 为什么有些命令只能在渲染通道之外记录?
- keras - (深度学习,rnn,cnn)图像图像 captinoing 与 keras
- javascript - 单击单选按钮时禁用复选框
- c# - 如何在 ASP.NET MVC 的剃刀视图中使用多个单独的模型?
- php - FFMPEG - 它从 .avi 获取帧,但不适用于 mp4
- arrays - “在这种情况下”使用数组会产生什么不良后果?
- java - 如何全局设置我的 JEE REST 客户端标头?
- bash - 无法使用 xagrs 直接将带引号的字符串传递给 rm