【问题标题】:Recyclerview getting refreshed after come back from another screen - Android navigation从另一个屏幕返回后 Recyclerview 刷新 - Android 导航
【发布时间】:2022-04-27 17:45:39
【问题描述】:

我有一个产品列表页面。 recyclerview 填充了来自 Firebase Firestore 的数据。当我点击任何产品时,它会转到详细信息页面。

view.findNavController().navigate(R.id.action_nav_products_to_productDetailFragment, bundle)

但是如果我点击后退按钮,我会调用 popBackStack() 并返回到上一个屏幕并重新加载。

findNavController().popBackStack()

如果我也单击系统后退按钮,也会发生相同的行为。

我查看了其他一些 Stackoverflow 帖子并遵循了一些答案。但没有任何帮助。

我尝试的是,在 onCreateView 中检查适配器初始化,如果已经初始化,则不会设置 recylerview 的适配器。但是应用了这个逻辑之后,我才知道,即使我没有将适配器设置为recyclerview,它也会自动重新加载。

我检查了谷歌文档提供的样本,这些样本运行良好。但我可以看到我的情况的唯一区别是 Firestore。

implementation 'com.google.firebase:firebase-firestore-ktx:22.1.2'
implementation 'com.google.firebase:firebase-database:19.7.0'
implementation 'com.google.firebase:firebase-storage-ktx:19.2.2'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation "androidx.navigation:navigation-fragment:$2.4.0-alpha01"
implementation "androidx.navigation:navigation-ui:$2.4.0-alpha01"
implementation "androidx.navigation:navigation-fragment-ktx:$2.4.0-alpha01"
implementation "androidx.navigation:navigation-ui-ktx:$2.4.0-alpha01"

我也尝试了一个稳定版本的导航。但同样的行为。

基本片段代码

abstract class BaseFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        parent: ViewGroup?,
        savedInstanseState: Bundle?
    ): View? {
        val view =  getFragmentView(inflater, parent, savedInstanseState)
        view.findViewById<Toolbar>(R.id.toolbar)?.let {
            it.title = getTitle()
            it.setNavigationOnClickListener { (activity as HomeActivity).openDrawer() }
        }
        return view
    }

    abstract fun getFragmentView(
        inflater: LayoutInflater,
        parent: ViewGroup?,
        savedInstanceState: Bundle?
    ): View

    abstract fun getTitle():String
}

在下方列出片段代码

class ProductsFragment : BaseFragment() {

    private val productsViewModel: ProductsViewModel by activityViewModels()
    private val categoryViewModel: CategoryViewModel by activityViewModels()

    override fun getFragmentView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        setUpProductsList()
        return inflater.inflate(R.layout.fragment_products, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        addFab.setOnClickListener {
            findNavController().navigate(R.id.action_nav_products_to_addProductsFragment)
        }
        txtSearch.addTextChangedListener {
            productsViewModel.getProduct(txtSearch.text.toString())
        }
    }

    override fun getTitle(): String {
        return resources.getString(R.string.menu_products)
    }

    private fun setUpProductsList(){
        categoryViewModel.getCategories("").observe(this, Observer {categories->
            productsViewModel.getProduct("").observe(this, Observer {products->
                products.let {
                    val adapter = ProductListingAdapter( products, categories, requireActivity())
                    productRV.adapter = adapter
                    productRV.layoutManager = LinearLayoutManager(requireContext())
                }
            })
        })
    }
}

如果您需要更多信息,请发表评论。我会更新答案。

【问题讨论】:

  • 能否分享您设置适配器的片段代码。
  • 我需要检查片段类的代码。您在适配器中设置数据的位置。
  • @MuhammadZahabAhmadKhan 更新了代码
  • 那么实际上你的问题是什么,失去你的滚动位置或其他什么?您的categoryViewModelproductsViewModel 将缓存您最后返回的数据的LiveData 存储在哪里,以便在Fragment 从后台堆栈返回时立即可用?
  • 您的代码设置方式(每次数据更改时重置适配器)似乎已经导致您在每次数据更改时丢失滚动位置的问题。您是否有理由在这部分做错了,而不是使用新数据更新适配器并使用notifyDataSetChanged() 等?

标签: android google-cloud-firestore android-recyclerview android-jetpack android-jetpack-navigation


【解决方案1】:

onDestroyView() 会在进入详细屏幕或另一个屏幕时被调用,因此很明显 onCreateView() 会在用户从另一个屏幕返回时被调用。重新创建视图,添加内容,最后放大视图。所以自动第一个可见项应该是第零个索引。

大多数开发人员都面临此类问题。

如何处理: -> 只有当适配器没有任何内容时,我们才需要从 ViewModel/repository 中获取内容。下面是代码相关的sn-p,希望对你有帮助。

  1. 适配器创建

    private var adapter: MyAdapter? = null

  2. 通过传递相关的东西从 onCreate() 初始化适配器

    adapter= MyAdapter(this)

  3. 大部分内容是从片段的 onViewCreated() 获取的。因此,只有当适配器中没有数据时,我们才需要获取并添加到适配器。

    if (adapter?.getItems()?.isEmpty() == true) fetchData() // could be io operation

它对我有用。

【讨论】:

    猜你喜欢
    • 2021-01-06
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 2019-10-10
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    相关资源
    最近更新 更多