DiffUtil重绘ListAdapter Kotline中的所有项目

DiffUtil redraw all items in ListAdapter Kotlin(DiffUtil重绘ListAdapter Kotline中的所有项目)
本文介绍了DiffUtil重绘ListAdapter Kotline中的所有项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Android Kotlin中使用DiffUtil和ListAdapter。我在onResume方法中从服务器调用数据。当onResume调用每一项时,整个数据都在重新绘制视图。如果服务器端有任何数据更改,我希望更新视图,以便它将反映在应用程序中。

ListActivity.kt

class ListActivity : BaseActivity() {

    lateinit var binding: ListActivityLayoutBinding
    private val viewModel: ListViewModel by inject()
    private var listAdapter: listAdapter? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupViewModel()
        binding = ListActivityLayoutBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }

    private fun setupViewModel() {
        viewModel.liveData.observe(this, { list ->
            setupAdapter(list)
        })
    }

    private fun setupAdapter(list: List<XYZ>) {
        initializeAdapter()
        listAdapter?.submitList(list)
        binding.recyclerView.adapter = listAdapter
    }

    private fun initializeAdapter() {
        viewModel.abc?.let { abc ->
            listAdapter = ListAdapter(abc, object : Listener<XYZ> {
                override fun selectedItem(item: XYZ) {
                    // calling 
                    }
                }
            })
        } ?: run {
            Log.e("Error", "Error for fetching data")
        }
    }

    override fun onResume() {
        super.onResume()
        viewModel.fetchData()
    }
}

XYZ.kt

data class XYZ(
    val id: String? = null,
    val title: String? = null,
    val count: Int? = null,
    val status: String? = null,
    val item: Qqq? = null
)

QQQ.kt

data class Qqq(
    val id: String? = null,
    val rr: Rr? = null
)

Rr.kt

data class Rr(
    val firstName: String? = null,
    val lastName: String? = null,
)

ListAdapter.kt

class ListAdapter(
    private val abc: Abc,
    private val listener: Listener <XYZ>
) : ListAdapter<XYZ, ListViewHolder>(LIST_COMPARATOR) {

    companion object {
        private val LIST_COMPARATOR = object : DiffUtil.ItemCallback<XYZ>() {
            override fun areItemsTheSame(oldItem: XYZ, newItem: XYZ): Boolean {
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(oldItem: XYZ, newItem: XYZ): Boolean {
                return ((oldItem.title == newItem.title) && (oldItem.status == newItem.status)
                        && (oldItem.count == newItem.count)
                        && (oldItem.item == newItem.item))
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
        return ListViewHolder.bindView(parent, abc)
    }

    override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
        holder.bindItem(getItem(position), listener)
    }
}

ListViewModel.Kt

class ListViewModel : BaseViewModel() {

    var abc: Abc? = null
    private var xyz: List<XYZ>? = null
    var liveData: MutableLiveData<List<XYZ>> = MutableLiveData()

    fun fetchData() {
        viewModelScope.launch {
          
            val firstAsync = async {
                if (abc == null) {
                    abc = getAbc() // First retrofit call
                }
            }
            val secondAsync = async {
                xyz = getXYZ() // Second retrofit call
            }
            firstAsync.await()
            secondAsync.await()
            liveData.postValue(xyz)
        }
    }
}

注意:我要检查abc在每次调用中都不是空的。

1.我的DiffUitll回调正确吗?

2.第一次调用我想要重画每一项,但是,如果我在onResume中调用viewModel.fetchData(),如果我需要做任何更改,否则我不想重画我的整个列表。有什么建议吗?

推荐答案

屏幕上闪烁的内容是因为您每次恢复时都会创建一个新的适配器实例,并且会重新触发您的viewModel订阅。

不要将适配器设置为后期初始化,这没有什么好处。

class ListActivity : BaseActivity() {

    lateinit var binding: ListActivityLayoutBinding
    private val viewModel: ListViewModel by inject()

    private val adapterListener = object : Listener<XYZ> {
                override fun selectedItem(item: XYZ) { // TODO  }
            }
           

    private var listAdapter = ListAdapter(adapterListener)

然后在可以的时候设置:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupViewModel()
        binding = ListActivityLayoutBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.yourRecyclerView.adapter = listAdapter
    }

然后,一旦观察到数据并获得它,就调用listAdapter.submitList(xxx)。除非您确实需要一个完整的新适配器(为什么?),否则无需重新创建适配器。

    private fun setupViewModel() {
        viewModel.liveData.observe(this, { list ->
            listAdapter.submitList(list.toMutableList())
        })
    }

的检查(&Q)

每次都需要调用一件事InitializeAdapter()函数,因为每次视图模型.abc都会检查该值不为空。

这就是ViewModel的问题。如果没有满足要求,你就不应该推一个新的清单。如果viewmodel.abc为空,则您在setupViewModel通过viewmodel.liveData.observe中提供的list不应存在,则您不应推送livedata或应推送其他状态。

片段应该对它接收到的数据做出反应,但是这些数据和逻辑的处理属于其他地方(视图模型和更深入的用例/报告)。

您的代码片段所做的一切就是构造框架的东西(一个循环视图及其附件,如Adapter、LayoutManager,如果需要,等等)。并订阅一个liveData流,该流将提供与框架内容连接所需的数据。它不会思考,也不应该这样做。

更新

Here is a Pull Request在我几分钟内抛出的样例项目中。当我运行该命令时,我在RecclerView的屏幕上看到两个模拟的项目。

这篇关于DiffUtil重绘ListAdapter Kotline中的所有项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

How to target newer versions in .gitlab-ci.yml using auto devops (java 11 instead of 8 and Android 31 instead of 29)(如何在.gitlab-ci.yml中使用自动开发工具(Java 11而不是8,Android 31而不是29)瞄准较新的版本)
Android + coreLibraryDesugaring: which Java 11 APIs can I expect to work?(Android+core LibraryDesugering:我可以期待哪些Java 11API能够工作?)
How to render something in an if statement React Native(如何在If语句中呈现某些内容Reaction Native)
How can I sync two flatList scroll position in react native(如何在本机Reaction中同步两个平面列表滚动位置)
Using Firebase Firestore in offline only mode(在仅脱机模式下使用Firebase FiRestore)
Crash on Google Play Pre-Launch Report: java.lang.NoSuchMethodError(Google Play发布前崩溃报告:java.lang.NoSuchMethodError)