最终在我的服务器中实现了设备类型的图标后,我用来自服务器的图标替换了以前使用的临时可绘制文件,并使用coil来加载它们.它们的ImageView在适配器BTW内.在第一次抽奖时,所有的东西都被正确地"对齐",标签和图像是正确的配对.但如果我进行某种排序,ImageView中的图像不再与标签对齐,或者它们完全消失了.我在我的应用程序中有一种行为,即首先我将从服务器获取并显示数据,如果本地数据与服务器的数据相同,那么我将只使用本地数据.但我认为这不会影响任何事情,因为我将服务器数据的每个字段都保存在数据库中.我还添加了一些日志(log),以查看coil应该检索哪个URL,并且它们是每个图标的正确URL.我调用notifyDatasetChanged()来重画适配器,因为排序返回的项长度可能与默认列表不同,默认列表就是我拥有的所有项.

下面是我的适配器的代码:

class ActuatorDeviceInfoAdapter(
    val ctx: FragmentActivity,
    var itemLst: MutableList<ActuatorDeviceInfo>,
    val showToggle: Boolean
) : RecyclerView.Adapter<ActuatorDeviceInfoAdapter.ViewHolder>() {
    private lateinit var binding: AdapterActuatorBinding
    var onItemClick: ((ActuatorDeviceInfo) -> Unit)? = null
    var onToggleClick: ((ActuatorDeviceInfo, Boolean, AdapterActuatorBinding) -> Unit)? = null

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ActuatorDeviceInfoAdapter.ViewHolder {
        binding = AdapterActuatorBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ActuatorDeviceInfoAdapter.ViewHolder, position: Int) {
        val pic = itemLst[position]
        holder.bind(pic)
    }

    override fun getItemCount(): Int = itemLst.size

    inner class ViewHolder(private val binding: AdapterActuatorBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(actuatorDeviceInfo: ActuatorDeviceInfo) {
            binding.actuatorDevInfo = actuatorDeviceInfo

            if (showToggle) {
                binding.tglStatus.visibility = View.VISIBLE
                binding.tglStatus.isChecked = actuatorDeviceInfo.status
            } else {
                binding.tglStatus.visibility = View.GONE
            }

            setIcon(actuatorDeviceInfo.type!!)
        }

        init {
            itemView.setOnClickListener {
                onItemClick?.invoke(itemLst[adapterPosition])
            }
            binding.tglStatus.setOnClickListener {
                onToggleClick?.invoke(itemLst[adapterPosition], binding.tglStatus.isChecked, binding)
            }
        }
    }

    private fun setIcon(type: ActuatorType) {
        val iconPath = "${Utils.instance.getServerHost(ctx)}${type.iconPath}"
        binding.imgIcon.load(iconPath)
    }

    companion object{
        const val TAG = "ActuatorDeviceInfoAdapter"
    }
}

推荐答案

问题出在专用功能setIcon中. 您需要使用每个ActuatorDeviceInfo更新每个项目的视图. 您需要使用项目视图的绑定来设置数据和图像.

Bind()中的for语句使用每个项的绑定. 但是SETIcon使用了一些其他绑定,该绑定具有上次初始化的视图,而根据您的要求,它不应该这样做.

  1. 删除变量private lateinit var binding: AdapterActuatorBinding.
  2. 在onCreateViewHolder函数中将局部变量绑定声明为val binding = .
  3. 将私有的SETIcon函数移动到ViewHolder类.

以上1、2步为可选步骤.

结果

class ActuatorDeviceInfoAdapter(
    val ctx: FragmentActivity,
    var itemLst: MutableList<ActuatorDeviceInfo>,
    val showToggle: Boolean
) : RecyclerView.Adapter<ActuatorDeviceInfoAdapter.ViewHolder>() {
    // 1. Removed
    // private lateinit var binding: AdapterActuatorBinding
    var onItemClick: ((ActuatorDeviceInfo) -> Unit)? = null
    var onToggleClick: ((ActuatorDeviceInfo, Boolean, AdapterActuatorBinding) -> Unit)? = null

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ActuatorDeviceInfoAdapter.ViewHolder {
        // 2. Declared
        val binding = AdapterActuatorBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ActuatorDeviceInfoAdapter.ViewHolder, position: Int) {
        val pic = itemLst[position]
        holder.bind(pic)
    }

    override fun getItemCount(): Int = itemLst.size

    inner class ViewHolder(private val binding: AdapterActuatorBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(actuatorDeviceInfo: ActuatorDeviceInfo) {
            binding.actuatorDevInfo = actuatorDeviceInfo

            if (showToggle) {
                binding.tglStatus.visibility = View.VISIBLE
                binding.tglStatus.isChecked = actuatorDeviceInfo.status
            } else {
                binding.tglStatus.visibility = View.GONE
            }

            setIcon(actuatorDeviceInfo.type!!)
        }
        // 3. Moved
        private fun setIcon(type: ActuatorType) {
            val iconPath = "${Utils.instance.getServerHost(ctx)}${type.iconPath}"
            binding.imgIcon.load(iconPath)
        }

        init {
            itemView.setOnClickListener {
                onItemClick?.invoke(itemLst[adapterPosition])
            }
            binding.tglStatus.setOnClickListener {
                onToggleClick?.invoke(itemLst[adapterPosition], binding.tglStatus.isChecked, binding)
            }
        }
    }

    

    companion object{
        const val TAG = "ActuatorDeviceInfoAdapter"
    }
}

您可以通过遵循最佳实践来避免此类问题.

  • 不要在嵌套块或内部类中声明相同的变量名(变量隐藏)

Android相关问答推荐

如何在Android Room中使用@Relation多对一查询

如何从LazyColumn中的图标异步获取可绘制的加载?

将DiffUtils用于Android上的Recrecerview适配器

在内部创建匿名对象的繁忙循环调用函数会产生开销吗?

在Jetpack Compose中实现自动换行

AndroidX Media3 迁移指南

升级到 Jetpack Compose 物料 list 2023.08.00 需要我将 targetSdk 更改为 34

使用不同的gradle文件导入外部库

在本地通知中设置自定义声音

当 Firebase Firestore 发生变化时,Kotlin ViewModel 不会更新

具有数据库和升级潜力的移动应用程序开发(Android)供朋友使用

@Immutable 对数据类有什么好处?

列表更改时,RecyclerView 中的列表不会更新

Kotlin 协程、 retrofit 、android

如何关闭可组合对话框?

如何从我的 android 应用程序中删除 QUERY_ALL_PACKAGES 权限?

如何在 kotlin 的 android room DB 中设置一对多关系

Jetpack Compose 中的按钮上的文本未更新

Android:在模块 jetified-play-services-measurement 和 jetified-play-services-measurement-impl 中发现重复类

未使用的内容填充参数