android - 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,但再次更改后文本不再更新:
解决方案
推荐阅读
- windows - Windows App 版本:认证完成后可以取消(发布手册)
- python - 在python中交换大小写的脚本
- javascript - 如何使用 justifyContent 和 alignItems 与 contentContainerStyle 等反应原生平面列表
- react-native - Google 地图未使用新的 API 密钥加载
- reactjs - 位跟踪 React 组件的全局上下文
- html - 使用 moment.js 来指示 mongoDB/mongoose 上次更新的时间?
- notepad++ - 如何用记事本++中的一个共同点替换所有单词
- javascript - 如何使用 javaScript 文件作为其他 JavaScript 文件的高阶包装器
- r - 将向量列表转换为数据框
- node.js - 如何使用 NodeJS 13 和 Typescript 3.8 导入 esm 模块?