本文介绍了流不使用绑定适配器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于特定的回收器视图项目,如果我选择Checkbox(勾选它),则需要将其对应的TextView文本格式化为删除线

我正在使用绑定适配器、流和实时数据。
但选中该复选框后,其对应的TextView未格式化。

但是,如果我导航到其他片段并返回到此处(FruitFragmnet),则TextView数据是格式化的。(即数据库在勾选复选框中正确更新,但实时数据发送延迟到UI)

可能的根本原因:我正在立即更新聊天室数据库,但LiveData没有立即从数据库传送到UI。

我做了很多试验和错误,阅读了多个类似的问题,但我找不到缺少的环节和此问题的解决方案。

请指教。代码如下:

BindingAdapter

@BindingAdapter("markAsCompleted")
fun markAsCompleted(textView: TextView, completed: Boolean) {
    if (completed) {
        textView.paintFlags = textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
    } else {
        textView.paintFlags = textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG.inv()
    }
}
@BindingAdapter("setItems")
fun setItems(view: RecyclerView, items: List<Fruit>?) {
    items?.let {
        (view.adapter as SettingAdapter).submitList(items)
    }
}

带回收器视图的水果碎片

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
    <variable
        name="settingViewModel"
        type="com.example.ui.SettingViewModel" />
</data>
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/fruits_list"
            setItems="@{settingViewModel.allList}" // This is Binding Adapter
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</layout>

上面的水果片段项目视图

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <import type="android.widget.CompoundButton" />
        <variable
            name="fruit"
            type="com.example.data.Fruit" />
        <variable
            name="settingViewModel"
            type="com.example.ui.SettingViewModel" />
    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
         ...
        <CheckBox
            android:id="@+id/fruit_checkbox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="@{fruit.completed}"
            android:onClick="@{(view) -> settingViewModel.completeFruit(fruit,((CompoundButton)view).isChecked())}"
             />

        <TextView
            android:id="@+id/fruit_name"
            markAsCompleted="@{fruit.completed}" // This is Binding Adapter
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="@{fruit.fruit}" />
          ....

水果碎片

class FruitFragment : Fragment() {
    private lateinit var binding: FragmentFruitBinding
    private lateinit var fruitAdapter: FruitAdapter
    private val viewModel: SettingViewModel by activityViewModels()
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentFruitBinding.inflate(layoutInflater, container, false).apply {
            lifecycleOwner = viewLifecycleOwner
            settingViewModel = viewModel
        }
        return binding.root
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        fruitAdapter = FruitAdapter(viewModel)
        binding.fruitslist.apply {
            adapter = fruitAdapter
        }
    }
}

SettingViewModel

class SettingViewModel(application: Application) : AndroidViewModel(application) {

    private val app = getApplication<Application>()
    private val dao = Database.getDatabase(app.applicationContext).dao

    val allList: LiveData<List<Fruit>> = dao.getFruits().asLiveData().distinctUntilChanged()

    fun completeFruit(fruit: Fruit, completed: Boolean) {
        viewModelScope.launch {
            if (completed) {
                dao.updateCompleted(fruit.id, completed)
            } else {
                dao.updateCompleted(fruit.id, completed)
            }
        }
    }
  ....
}

DAO类

@Dao
interface DatabaseDao {

    @Query("SELECT * FROM fruit_table")
    fun getFruits(): Flow<List<Fruit>>

    @Query("UPDATE fruit_table SET completed = :completed WHERE id = :id")
    suspend fun updateCompleted(id: Int, completed: Boolean)
    }

回收视图适配器

class FruitAdapter(private val viewModel: SettingViewModel) : ListAdapter<Fruit, ViewHolder>(FruitDiffCallback()) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder.from(parent)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = getItem(position)
        holder.bind(item, viewModel)
    }

    class ViewHolder private constructor(val binding: ContainerFruitBinding) : RecyclerView.ViewHolder(binding.root) {

        fun bind(item: Fruit, viewModel: SettingViewModel) {
            binding.apply {
                settingViewModel = viewModel
                fruit = item
                executePendingBindings()
            }
        }

        companion object {
            fun from(parent: ViewGroup): ViewHolder {
                val layoutInflater = LayoutInflater.from(parent.context)
                val binding = ContainerFruitBinding.inflate(layoutInflater, parent, false)
                return ViewHolder(binding)
            }
        }
    }
}

class FruitDiffCallback : DiffUtil.ItemCallback<Fruit>() {
    override fun areItemsTheSame(oldItem: Fruit, newItem: Fruit): Boolean {
        return oldItem.id == newItem.id
    }

    override fun areContentsTheSame(oldItem: Fruit, newItem: Fruit): Boolean {
        return oldItem.fruit == newItem.fruit
    }
}

数据类

@Entity(tableName = "fruit_table")
data class Fruit(
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0,
    var fruit: String,
    var completed: Boolean = false
)

推荐答案

我想您需要将setItems函数的第二个参数更改为BindingAdapter中的LiveData

@BindingAdapter("setItems")
fun setItems(view: RecyclerView, data: LiveData<List<Fruit>>) {
    data.value?.let {
        (view.adapter as SettingAdapter).submitList(it)
    }
}

这篇关于流不使用绑定适配器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 17:53