使用分页库和导航体系结构组件将recyclerview的状态保持在片段中

Sli*_*169 9 android android-recyclerview android-architecture-navigation android-paging

我正在使用jetpack的2个组件:分页库和导航。

就我而言,我有2个片段:ListMoviesFragment和MovieDetailFragment

当我滚动一定距离并单击recyclerview的电影项目时,MovieDetailFragment被附加,并且ListMoviesFragment在后堆栈中。然后我按返回按钮,ListMoviesFragment从后退堆栈中恢复。

该点是滚动位置,并且ListMoviesFrament的项被重置,就像第一次附加到其活动一样。因此,如何保持recyclerview的状态以防止这种情况?

换句话说,如何使用FragmentTransaction以传统方式但以现代方式(导航)保留整个片段的状态,例如隐藏/显示片段

我的示例代码:

片段布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:tools="http://schemas.android.com/tools"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         tools:context="net.karaokestar.app.SplashFragment">

<TextView
        android:id="@+id/singer_label"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="Ca s?"
        android:textColor="@android:color/white"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@+id/btn_game_more"
        android:layout_centerVertical="true"
        android:background="@drawable/shape_label"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="@dimen/header_margin_bottom_list"
        android:textStyle="bold"
        android:padding="@dimen/header_padding_size"
        android:textAllCaps="true"/>


<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/list_singers"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
Run Code Online (Sandbox Code Playgroud)

片段Kotlin代码:

    package net.karaokestar.app
    import android.os.Bundle
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.fragment.app.Fragment
    import androidx.lifecycle.LiveData
    import androidx.lifecycle.Observer
    import androidx.navigation.fragment.findNavController
    import androidx.paging.LivePagedListBuilder
    import androidx.paging.PagedList
    import androidx.recyclerview.widget.LinearLayoutManager
    import kotlinx.android.synthetic.main.fragment_splash.*
    import net.karaokestar.app.home.HomeSingersAdapter
    import net.karaokestar.app.home.HomeSingersRepository

    class SplashFragment : Fragment() {

        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_splash, container, false)
        }

        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            val singersAdapter = HomeSingersAdapter()
            singersAdapter.setOnItemClickListener{
findNavController().navigate(SplashFragmentDirections.actionSplashFragmentToSingerFragment2())
}
            list_singers.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
            list_singers.setHasFixedSize(true)
            list_singers.adapter = singersAdapter

            getSingersPagination().observe(viewLifecycleOwner, Observer {
                singersAdapter.submitList(it)
            })
        }

        fun getSingersPagination() : LiveData<PagedList<Singer>> {
            val repository = HomeSingersRepository()
            val pagedListConfig = PagedList.Config.Builder().setEnablePlaceholders(true)
                .setPageSize(Configurations.SINGERS_PAGE_SIZE).setPrefetchDistance(Configurations.SINGERS_PAGE_SIZE).build()

            return LivePagedListBuilder(repository, pagedListConfig).build()
        }
    }
Run Code Online (Sandbox Code Playgroud)

小智 2

请尝试以下步骤:

  1. 初始化您的适配器onCreate而不是onCreateView. 保留一次初始化,并将其附加到onCreateView或中onViewCreated
  2. 不要getSingersPagination()每次都从方法返回 pagedList 的新实例,而是将其存储在伴随对象中或ViewModel(首选)并重用它。

检查以下代码以大致了解要做什么:

class SingersViewModel: ViewModel() {
   private var paginatedLiveData: MutableLiveData<YourType>? = null;

   fun getSingersPagination(): LiveData<YourType> {
      if(paginatedLiveData != null) 
         return paginatedLiveData;
      else {
         //create a new instance, store it in paginatedLiveData, then return
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

您的问题的原因是:

  1. 您每次都会连接一个新适配器,因此它会跳到顶部。
  2. 您每次都会创建新的分页列表,因此它会跳到顶部,认为数据都是新的。

  • 尽管我的问题已经消失很多年了,但我想我会给你一个复选标记。因为我知道未经我的测试它是正确的 (2认同)