繁体   English   中英

不会notifyDataSetChanged() 在Android Studio 的RecyclerView.ViewHolder 中启动init{ } 吗?

[英]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只是一个类,因此您可以传递它并且不会给出任何错误。 我现在能想到不这样做的原因如下:-

  1. 通过传递ViewModel将适配器与单个ViewModel紧密耦合,即ViewModel为 Activity 或片段。 现在你不能在任何其他地方重用这个适配器

  2. 同样,拥有ViewModel的全部意义在于观察通常不会发生在 Adapter 内部的数据流。

记住一件事ViewModel (LiveData) 不是回调接口的替代品。 所以你应该在这里使用回调接口,因为你在这里不需要生命周期组件。

因此,不要直接将ViewModel传递给适配器,而是将数据集传递给适配器如果您需要在操作(单击、长按)上通知ActivityFragment ,请使用接口。

init将在创建ViewHolder时调用一次。 这就是为什么RecyclerView有 recycle 一词的原因。 它将重用它的对象。 因此initViewHolder的生命周期中只会被调用一次。 当内容可见(或接近可见)时,将调用bind bind调用setControl

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM