程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了带有 DiffUtil 更新大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决带有 DiffUtil 更新?

开发过程中遇到带有 DiffUtil 更新的问题如何解决?下面主要结合日常开发的经验,给出你关于带有 DiffUtil 更新的解决方法建议,希望对你解决带有 DiffUtil 更新有所启发或帮助;

如何使用 DiffUtil 回调处理 RecyclerVIEw 的 onClick?以及如何在 recyclervIEw 中更改所选项目的背景颜色?我在一个活动中有两个 RecyclerVIEws。当用户点击 RecyclerVIEw A 中的项目时,RecyclerVIEw B 中会发生一些事情。

这是课堂

import androIDx.room.columnInfo

data class SkladTuple(
    @columnInfo(name = "sklad") val sklad: Int?,@columnInfo(name = "reg") val reg: Int?
)

这是适配器:

class SkladAdapter: listadapter<SkladTuple,SkladAdapter.PolozkaVIEwHolder>(DiffCallBACk())
{
    overrIDe fun onCreateVIEwHolder(parent: VIEwGroup,vIEwType: int): PolozkaVIEwHolder {
        val binding = SkladyItembinding.inflate(LayoutInflater.from(parent.context),parent,falsE)
        return PolozkaVIEwHolder(binding)
    }

    overrIDe fun onBindVIEwHolder(holder: PolozkaVIEwHolder,position: int) {
        val currentItem = getItem(position)
        holder.bind(currentItem)  

    }
    class PolozkaVIEwHolder(private val binding: SkladyItembinding): RecyclerVIEw.VIEwHolder(binding.root){
        fun bind(polozkaSklad: SkladTuplE){
            binding.apply {
                tvSklad.text = polozkaSklad.sklad.toString()
                tvRegal.text = polozkaSklad.reg.toString()

            }
        }
    }
    class DiffCallBACk: DiffUtil.ItemCallBACk<SkladTuple>(){
        overrIDe fun areItemsTheSame(oldItem: SkladTuple,newItem: SkladTuplE) =
            oldItem.sklad == newItem.sklad

        overrIDe fun areContentsTheSame(oldItem: SkladTuple,newItem: SkladTuplE) =
            oldItem == newItem
    }
}

这是活动

@AndroIDEntryPoint
class DokladActivity : AppCompatActivity() {
    private val skladviewmodel: Skladviewmodel by viewmodels()
    overrIDe fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceStatE)
        val binding = ActivityDokladBinding.inflate(layoutInflater)
        setContentVIEw(binding.root)
        binding.btVybratDoklad.setonClickListener{
            openActivity(binding.root)
        }
        val skladAdapter = SkladAdapter()
        val dokladAdapter = DokladAdapter()
        binding.apply {
            recyclerVIEwSklady.apply {
                adapter = skladAdapter

                layoutManager = linearlayoutmanager(this@DokladActivity)
            }
            skladviewmodel.skladyPolozky.observe(this@DokladActivity) {
                skladAdapter.submitList(it)
                Log.d("Doklad",skladAdapter.currentList.toString())
            }

            recyclerVIEwDoklady.apply {
                adapter = dokladAdapter
                layoutManager = linearlayoutmanager(this@DokladActivity)
            }
            skladviewmodel.dokladyPolozky.observe(this@DokladActivity){
                dokladAdapter.submitList(it)
                Log.d("Doklad",dokladAdapter.currentList.toString())
            }
        }


    }

    fun openActivity(vIEw: VIEw){
        val intent = Intent(this,PolozkaActivity::class.java )
        startActivity(intent)
    }
}


这是视图模型

@Hiltviewmodel
class Skladviewmodel @Inject constructor(
    repository: SybaseRepository
): viewmodel(){
    val skladyPolozky = repository.getAllSkladFromPolozka().asliveData()
    val dokladyPolozky = repository.getAllHlavickyTodoklad().asliveData()
}

这是布局 - 我有两个回收站视图。当用户点击 recyclervIEw A 中的项目时,recyclervIEw B 中会发生一些事情

<?xml version="1.0" enCoding="utf-8"?>
<androIDx.consTraintlayout.Widget.ConsTraintLayout xmlns:androID="http://scheR_235_11845@as.androID.com/apk/res/androID"
    xmlns:app="http://scheR_235_11845@as.androID.com/apk/res-auto"
    xmlns:tools="http://scheR_235_11845@as.androID.com/tools"
    androID:layout_wIDth="match_parent"
    androID:layout_height="match_parent">

    <androIDx.consTraintlayout.Widget.GuIDeline
        androID:ID="@+ID/guIDeline8"
        androID:layout_wIDth="wrap_content"
        androID:layout_height="wrap_content"
        androID:orIEntation="horizontal"
        app:layout_consTraintGuIDe_percent="0.02" />

    <androIDx.consTraintlayout.Widget.GuIDeline
        androID:ID="@+ID/guIDeline9"
        androID:layout_wIDth="wrap_content"
        androID:layout_height="wrap_content"
        androID:orIEntation="vertical"
        app:layout_consTraintGuIDe_percent="0.7" />

    <androIDx.consTraintlayout.Widget.GuIDeline
        androID:ID="@+ID/guIDeline10"
        androID:layout_wIDth="wrap_content"
        androID:layout_height="wrap_content"
        androID:orIEntation="horizontal"
        app:layout_consTraintGuIDe_percent="0.25" />

    <androIDx.consTraintlayout.Widget.GuIDeline
        androID:ID="@+ID/guIDeline11"
        androID:layout_wIDth="wrap_content"
        androID:layout_height="wrap_content"
        androID:orIEntation="horizontal"
        app:layout_consTraintGuIDe_percent="0.75" />

    <androIDx.consTraintlayout.Widget.GuIDeline
        androID:ID="@+ID/guIDeline12"
        androID:layout_wIDth="wrap_content"
        androID:layout_height="wrap_content"
        androID:orIEntation="horizontal"
        app:layout_consTraintGuIDe_percent="0.9" />

    <tableLayout
        androID:stretchcolumns="1,2"
        androID:layout_margin="8dp"
        androID:layout_wIDth="0dp"
        androID:layout_height="0dp"
        androID:layout_marginStart="8dp"
        androID:layout_margintop="8dp"
        androID:layout_marginEnd="8dp"
        androID:layout_marginBottom="8dp"
        app:layout_consTraintBottom_totopOf="@+ID/guIDeline10"
        app:layout_consTraintEnd_toStartOf="@+ID/guIDeline9"
        app:layout_consTraintStart_toStartOf="parent"
        app:layout_consTrainttop_totopOf="@+ID/guIDeline8">

        <tableRow>
            <TextVIEw
                androID:text="SKLAD"
                androID:textSize="16dp"
                androID:textStyle="bold"
                androID:padding="10dp"
                androID:layout_gravity="center"
                androID:layout_column="1"/>
            <TextVIEw
                androID:text="REgal"
                androID:textSize="16dp"
                androID:textStyle="bold"
                androID:padding="10dp"
                androID:layout_gravity="center"
                androID:layout_column="1"/>
        </tableRow>

        <androIDx.recyclervIEw.Widget.RecyclerVIEw
            xmlns:app="http://scheR_235_11845@as.androID.com/apk/res-auto"
            androID:ID="@+ID/recycler_vIEw_sklady"
            androID:scrollbars="vertical"
            androID:layout_wIDth="match_parent"
            androID:layout_height="wrap_content"
            tools:Listitem="@layout/sklady_item"
            />

    </tableLayout>

<tableLayout
    androID:layout_wIDth="0dp"
    androID:layout_height="0dp"
    androID:layout_marginStart="8dp"
    androID:layout_margintop="8dp"
    androID:layout_marginEnd="16dp"
    androID:layout_marginBottom="8dp"
    androID:stretchcolumns="1,2,3,4,5"
    app:layout_consTraintBottom_totopOf="@+ID/guIDeline11"
    app:layout_consTraintEnd_toEndOf="parent"
    app:layout_consTraintStart_toStartOf="parent"
    app:layout_consTrainttop_totopOf="@+ID/guIDeline10"
    >
    <tableRow>
        <TextVIEw
            androID:layout_column="1"
            androID:layout_gravity="center"
            androID:padding="10dp"
            androID:text="U"
            androID:textSize="16dp"
            androID:textStyle="bold" />
        <TextVIEw
            androID:layout_column="1"
            androID:layout_gravity="center"
            androID:padding="10dp"
            androID:text="DOKL"
            androID:textSize="16dp"
            androID:textStyle="bold" />
        <TextVIEw
            androID:layout_column="1"
            androID:layout_gravity="center"
            androID:padding="10dp"
            androID:text="ODB"
            androID:textSize="16dp"
            androID:textStyle="bold" />
        <TextVIEw
            androID:layout_column="1"
            androID:layout_gravity="center"
            androID:padding="10dp"
            androID:text="ORG"
            androID:textSize="16dp"
            androID:textStyle="bold" />
        <TextVIEw
            androID:layout_column="1"
            androID:layout_gravity="center"
            androID:padding="10dp"
            androID:text="DATUM"
            androID:textSize="16dp"
            androID:textStyle="bold" />

    </tableRow>


    <androIDx.recyclervIEw.Widget.RecyclerVIEw
        xmlns:app="http://scheR_235_11845@as.androID.com/apk/res-auto"

        androID:ID="@+ID/recycler_vIEw_doklady"
        androID:scrollbars="vertical"
        androID:layout_wIDth="match_parent"
        androID:layout_height="wrap_content"
        tools:Listitem="@layout/doklady_item"/>
</tableLayout>

    <button
        androID:ID="@+ID/bT_Back"
        androID:layout_wIDth="wrap_content"
        androID:layout_height="wrap_content"
        androID:layout_marginStart="24dp"
        androID:text="Zpět"
        app:layout_consTraintBottom_toBottomOf="parent"
        app:layout_consTraintStart_toStartOf="parent"
        app:layout_consTrainttop_totopOf="@+ID/guIDeline12" />

    <button
        androID:ID="@+ID/bt_vybrat_doklad"
        androID:layout_wIDth="wrap_content"
        androID:layout_height="wrap_content"
        androID:layout_marginEnd="24dp"
        androID:text="Vybrat doklad"
        app:layout_consTraintBottom_toBottomOf="parent"
        app:layout_consTraintEnd_toEndOf="parent"
        app:layout_consTrainttop_totopOf="@+ID/guIDeline12" />

    <TextVIEw
        androID:ID="@+ID/textVIEw2"
        androID:layout_wIDth="209dp"
        androID:layout_height="50dp"
        androID:layout_marginStart="24dp"
        androID:layout_margintop="16dp"
        androID:text="TextVIEw"
        app:layout_consTraintBottom_totopOf="@+ID/guIDeline12"
        app:layout_consTraintEnd_toStartOf="@+ID/guIDeline9"
        app:layout_consTraintStart_toStartOf="parent"
        app:layout_consTrainttop_totopOf="@+ID/guIDeline11" />
</androIDx.consTraintlayout.Widget.ConsTraintLayout>

解决方法

怎么可能……

您有一个 ViewModel,它使用 RecyclerViews 需要的 List(两个适配器,两个列表)公开了两个可观察的 liveData。

决定List A,Item 1被点击,因此List B,Item N必须改变背景的逻辑绝对超出 Recycler View,Adapter,Activity,甚至可能是 ViewModel。

最终,当发生数据突变时(您点击了第 1 项),您会收到此事件,对其采取行动(又名:将其发送到 Viewmodel -> Repository -> 转换数据 ->发布包含变异数据的新列表。

最终,您的 ViewModel 将从存储库接收新数据,并将更新您的活动正在观察的 LiveData(s),这将导致适配器提交新数据,您的 DiffUtils 将获取这些数据,导致Adapter 重新绑定修改后的视图。

更新

根据您链接的问题/答案以及您的评论,我认为这值得进一步评论。

  1. 此人说:“处理适配器上的点击或使用接口都不是一个好主意”,然后继续“处理”点击,使用匿名函数(所以它可能是一个用于测试目的的接口,但它使它成为一个“高阶函数”。

  2. 这和我描述的原理完全一样,只是接口更容易理解。

想想这样的责任:

ViewHolder:它对数据、回收器视图、适配器等一无所知。但它可以直接访问列表的每个“行/列”。它拥有视图,并且可以根据它提供的数据来操纵它们,并被告知“保留”在所需的视图旁边。它不创建视图(它被告知)但它有它们。关于点击,所有这些可以做的是公开一个视图(这样一个点击侦听器可以由外部设置)或简单地委托它。

Adapter:除了视图的类型(如果使用)以及如何创建 viewHolders 和“绑定”它们之外,它对视图一无所知。所以它介于两者之间,但它确实可以访问提供给它的数据源(您提供的列表),并且它确实可以访问它创建的每个“视图持有者”;它或多或少知道屏幕上的内容,并且可以将位置映射到数据。

RecyclerView/Fragment/ViewModel:它们不知道适配器内部发生了什么(也不应该),但它们主要对点击(或事件)何时发生感兴趣,因此它们大概可以对此做些什么。

基于所有这些,让我们看看 this person's solution(对比我的建议):

  1. 适配器的构造函数被修改为接收一个函数:

(private val onSELEct: (YourDataType?) -> Unit)

我通常定义一个接口:

interface SomethingClickListener {
  fun onSomethingICaredForHappened(something: Something)
}

并将其传递给我的适配器,但想法是相同的;我更喜欢这个界面,因为它更容易对具体类型使用依赖注入(并且更容易测试),但这只是我个人的偏好。

class YourAdapter(private val clickListener: SomethingClickListener)

  1. 适配器内部发生的事情是相同的原理。您需要在您希望被点击的视图上设置实际的点击侦听器(如果您希望整个“行”都可点击,则需要在整个 itemView 上设置)。

通过简单地使用单击侦听器的匿名实现并捕获发送到绑定方法的值(很好),您可以(或想要在那里做更多的事情),链接的答案就消失了。所以你可以使用另一个界面或这样做,本质上,想法是一样的,你正在传递点击事件

binding.root.setOnClickListener {
    onSELEct(yourDataTypE)
  }

因此它将 dataType 直接传递给 onSELEct(这是提供给适配器的函数)。在这个阶段,其中唯一的逻辑是附加与被点击的 viewBinding 相关联的“数据”,这是适配器/视图持有者可以并且应该提供的“唯一”信息。

在此 onSELEct 之后会发生什么,是您的片段/活动收到此信息,然后您应该调用您的 ViewModel 说:

viewModel.thisThingWasClicked(theThingYouReceived)

你明白了……

我有一段时间没有更新它(我想我是 3 年前用 Java 写的,然后我天真地将它转换为 Kt)除了更新库并确保它仍然可以编译,但是你可以看到“两个接口方法”(现在有点老派,可以通过 Kotlin 使用高阶函数),但仍然是相同的方法。

看看这个项目(特别是 adapter。

请注意,它接受 ThingClickListener,但在内部使用 ToggleListener 在 ViewHolders 和适配器之间进行通信。

最后,这可以简化为使用更少的界面。

我希望这能澄清这个想法。 请注意,除了处理 Click 侦听器和绑定正确数据之外,ViewHolder 和 Adapter 都没有任何责任。

大佬总结

以上是大佬教程为你收集整理的带有 DiffUtil 更新全部内容,希望文章能够帮你解决带有 DiffUtil 更新所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:带有更新