0

我正在使用新的ConcatAdapter和 Android 导航组件来创建一个复杂的 recyclerView,其中包含嵌套的水平滚动列表。我正在尝试恢复这些嵌套列表在旋转、导航等方面的状态。我已经阅读了关于该主题的这篇文章,但我正在努力解决如何在这种情况下恢复状态。

adapter.stateRestorationPolicy = PREVENT_WHEN_EMPTY我将它应用于包含嵌套回收器视图的适配器时,上面的文章中的内容不起作用。我在收到数据时尝试更新嵌套适配器,并尝试在数据接收时将它们添加到 concat 适配器,但没有成功。

我的片段

override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 
   
    val concatAdapter = ConcatAdapter()

    binding.recyclerView.apply {
        adapter = concatAdapter
        layoutManager = LinearLayoutManager(requireContext())
    }

    viewModel.data.observe(viewLifecycleOwner, { listItems ->
        concatAdapter.addAdapter(NestedListAdapter(listItems))
    })
}

也试过这个:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 
    val nestedListAdapter = NestedListAdapter()
    val concatAdapter = ConcatAdapter(nestedListAdapter)

    binding.recyclerView.apply {
        adapter = concatAdapter
        layoutManager = LinearLayoutManager(requireContext())
    }

    viewModel.movies.observe(viewLifecycleOwner, { items ->
        nestedListAdapter.clearItems()
        nestedListAdapter.addItems(items)
        nestedListAdapter.notifyItemRangeChanged(0, items.size)
    })
}

我还尝试延迟将适配器绑定到外部 recyclerview:

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 
    lateinit var concatAdapter: ConcatAdapter()

    binding.recyclerView.apply {
        layoutManager = LinearLayoutManager(requireContext())
    }

    viewModel.movies.observe(viewLifecycleOwner, { items ->

        concatAdapter = ConcatAdapter(MovieHorizontalListAdapter(it.data.toMutableList()))

        if (binding.recyclerView.adapter != concatAdapter) {
            binding.recyclerView.adapter = concatAdapter
        }

    })
}

我的嵌套 Recyclerview 适配器

class NestedListAdapter(
     private val listItems: MutableList<Movie> = mutableListOf()
) : RecyclerView.Adapter<NestedListAdapter.ViewHolder>() {
private val scrollStates: MutableMap<String, Parcelable?> = mutableMapOf()
private val viewPool = RecyclerView.RecycledViewPool()

init {
    // this does not do anything, (it's also added in the MovieListAdapter)
    stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY
}

private fun getSectionID(position: Int): String {
    return listItems.getOrNull(position)?.id?.toString().orEmpty()
}

override fun onViewRecycled(holder: ViewHolder) {
    super.onViewRecycled(holder)

    val key = getSectionID(holder.layoutPosition)
    scrollStates[key] = holder.rv.layoutManager?.onSaveInstanceState()
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val binding = NestedListAdapterBinding.inflate(
        LayoutInflater.from(parent.context),
        parent,
        false
    )

    return ViewHolder(binding)
}

override fun getItemCount(): Int = if (listItems.isEmpty()) 0 else 1

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bind(listItems)
}

inner class ViewHolder(
    binding: NestedListAdapterBinding
) : RecyclerView.ViewHolder(binding.root) {
    val rv = binding.recyclerView

    fun bind(listItems: List<Movie>) {
        val lm = LinearLayoutManager(rv.context, HORIZONTAL, false)
        lm.initialPrefetchItemCount = 4

        rv.apply {
            setRecycledViewPool(viewPool)
            layoutManager = lm
            adapter = MovieListAdapter(listItems)
        }

        restoreState()
    }

    // This is to restore the state when recycling items (not rotation)
    private fun restoreState() {
        val key = getSectionID(layoutPosition)
        val state = scrollStates[key]
        if (state != null) {
            rv.layoutManager?.onRestoreInstanceState(state)
        } else {
            val padding = rv.resources.getDimension(R.dimen.default_padding).toInt()
            rv.addItemDecoration(HorizontalListMarginDecoration(padding))
            rv.layoutManager?.scrollToPosition(0)
        }
    }
}

任何帮助表示赞赏。

4

0 回答 0