首页 > 解决方案 > SeekBar 双向数据绑定不更新 TextView

问题描述

我有一个带有 SeekBar 和 TextView 的数据绑定布局,应该显示所选值。起初,它可以工作,但是此布局位于具有其他数据绑定布局的 RecyclerView 内,滚动一段时间后,它停止工作(更改所选值时 TextView 停止更新)。我想这可能是适配器和绑定逻辑的问题,但我需要帮助来识别它。

这是布局文件(删除了其他视图、边距和约束以使其更具可读性):

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type=".EffectUiModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <SeekBar
            android:id="@+id/seekBarValue"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:max="100"
            android:progress="@={viewModel.seekSelection}"
             />

        <TextView
            android:id="@+id/txtSeekBarValue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewModel.seekSelection.toString()}"
            />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

这是数据模型:

class EffectUiModel(effect: Effect) : DataBoundModel(R.layout.effect_list_item) {

    val name = MutableLiveData<String>().apply { value = effect.name }
    val description = MutableLiveData<String>().apply { value = effect.description }
    val type = MutableLiveData<EffectType>().apply { value = effect.type }
    val seekSelection = MutableLiveData<Int>()
}

这个数据模型是从 DataBoundModel 扩展而来的,如你所见,它只是保存布局 ID 并将其用于回收逻辑:

open class DataBoundModel(@LayoutRes val layout: Int)

这里的整个想法是,我可以拥有一个内部包含不同数据绑定模型的 Recycler View,并且回收和绑定应该自动工作(到目前为止,除了这种情况外,它一直是这样)。这是适配器:

class DataBoundRecyclerAdapter(val items: List<DataBoundModel>) : RecyclerView.Adapter<DataBoundViewHolder>() {

    override fun getItemViewType(position: Int): Int {
        return items[position].layout
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataBoundViewHolder {
        val binding: ViewDataBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), viewType, parent, false)
        return DataBoundViewHolder(binding).also { binding.lifecycleOwner = it }
    }


    override fun getItemCount(): Int {
        return items.size
    }

    override fun onBindViewHolder(holder: DataBoundViewHolder, position: Int) {
        holder.binding.setVariable(BR.viewModel, items[position])
        holder.binding.executePendingBindings()
    }

    override fun onViewAttachedToWindow(holder: DataBoundViewHolder) {
        super.onViewAttachedToWindow(holder)
        holder.markAttach()
    }

    override fun onViewDetachedFromWindow(holder: DataBoundViewHolder) {
        super.onViewDetachedFromWindow(holder)
        holder.markDetach()
    }

}

这是 ViewHolder:

class DataBoundViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root), LifecycleOwner {

    private val lifecycleRegistry = LifecycleRegistry(this)

    fun markAttach() {
        lifecycleRegistry.currentState = Lifecycle.State.STARTED
    }

    fun markDetach() {
        lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
    }

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }

}

然后,我只需创建数据绑定模型并将它们添加到列表中,然后创建适配器并将其设置为回收器视图。这里可能有什么问题?

编辑:

这是布局错误后的图像,原始值为null,我选择了 85,在回收器视图上向下滚动,回来,搜索栏正确标记为 85,但再次更改后文本不再更新:

显示错误的图像

标签: androidmvvmandroid-recyclerviewdata-bindingandroid-databinding

解决方案


推荐阅读