首页 > 解决方案 > 导航离开后返回片段时如何恢复先前的滚动位置

问题描述

我在 Github 有以下项目:https ://github.com/AliRezaeiii/News-Cache

首先,我在 Fragment 中加载数据,显示来自数据库的数据,然后开始从 API 加载数据。从 API 加载完成后,我会更新数据库,并且 Fragment 中的 recyclerView 也会更新。

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel.news.observe(viewLifecycleOwner, Observer<List<Article>> { articles ->
            articles?.apply {
                viewModelAdapter.submitList(articles)
            }
        })
    }

这是我的适配器:

class NewsAdapter(val callback: OnClickListener) : ListAdapter<Article, NewsAdapter.NewsViewHolder>(DiffCallback) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = NewsViewHolder.from(parent)

    override fun onBindViewHolder(holder: NewsViewHolder, position: Int) {
        holder.bind(getItem(position), callback)
    }

    /**
     * Allows the RecyclerView to determine which items have changed when the [List] of [Article]
     * has been updated.
     */
    companion object DiffCallback : DiffUtil.ItemCallback<Article>() {
        override fun areItemsTheSame(oldItem: Article, newItem: Article): Boolean {
            return oldItem.url == newItem.url
        }

        override fun areContentsTheSame(oldItem: Article, newItem: Article): Boolean {
            return oldItem == newItem
        }
    }
}

当新数据从 API 到达时,我想滚动到 RecyclerView 的顶部:

handler.postDelayed({
            binding.recyclerView.scrollToPosition(0)
        }, 1000)

问题是当我转到详细信息屏幕并导航回主屏幕onActivityCreated并被onCreateView调用时,结果binding.recyclerView.scrollToPosition(0)也被调用,这不是我想要的。

当新数据从 API 到达时,滚动到 RecyclerView 顶部的解决方案是什么?

标签: androidandroid-recyclerview

解决方案


你可以很容易地解决这个问题,方法是按住 bool 作为指标。isFirstLoad

在开始观察新闻之前在 onActivityCreated 中将其设置为 true,然后在观察者中设置您想要执行的操作。

像这样的东西应该工作:

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        isFirstNewsFetch = true
        viewModel.news.observe(viewLifecycleOwner, Observer<List<Article>> { articles ->

            articles?.let { articles ->
                viewModelAdapter.submitList(articles)
                if(isFirstNewsFetch) {
                   isFirstNewsFetch = false
                 }else {
                  scrollToTop()
                 }
            }
        })
    }

作为旁注:

apply标准函数/范围函数应该用于对象配置。

供您使用let- Kotlin 标准函数备忘单


推荐阅读