RecyclerView状态保存失效:横竖屏切换后无法恢复滚动位置
RecyclerView横竖屏状态恢复失败问题排查与修复
问题根源
你的代码存在三个关键错误,导致滚动状态无法恢复:
状态处理位置错误
承载RecyclerView的是MoviesFragment,但你把状态保存/恢复逻辑放在了Activity中。横竖屏切换时Fragment会销毁重建,而你每次ActivityonCreate都新建MoviesFragment,旧Fragment的状态完全丢失,Activity保存的状态无法对应新Fragment的RecyclerView。状态恢复时机错误
你在Activity的onResume中尝试恢复状态,但此时新Fragment的RecyclerView或其LayoutManager可能还未初始化完成,调用onRestoreInstanceState自然无效。另外onRestoreInstanceState中先获取状态再调用super的顺序,也不符合Android组件生命周期的常规处理逻辑。静态变量存储状态的风险
使用companion object的静态变量保存状态,不仅可能造成内存泄漏,而且新Activity重建后,静态变量的状态与新创建的RecyclerView实例不匹配,恢复逻辑完全失效。
正确实现方案(移至Fragment处理)
将状态管理逻辑放到MoviesFragment中,利用Fragment自身的生命周期状态保存机制,才是正确的做法:
class MoviesFragment : Fragment() { private lateinit var recyclerView: RecyclerView private var layoutManagerState: Parcelable? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_movies, container, false) recyclerView = view.findViewById(R.id.recycler_view) // 初始化LayoutManager和Adapter recyclerView.layoutManager = LinearLayoutManager(requireContext()) recyclerView.adapter = YourMovieAdapter() // 替换为你的实际Adapter类 return view } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 在View创建完成后恢复状态 savedInstanceState?.let { bundle -> layoutManagerState = bundle.getParcelable("RECYCLER_STATE") recyclerView.layoutManager?.onRestoreInstanceState(layoutManagerState) } } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) // 保存LayoutManager的滚动状态 layoutManagerState = recyclerView.layoutManager?.onSaveInstanceState() outState.putParcelable("RECYCLER_STATE", layoutManagerState) } }
额外优化:Activity侧的Fragment创建逻辑
修改Activity的onCreate方法,避免横竖屏切换时重复创建Fragment:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 仅在首次创建时添加Fragment if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .replace(R.id.fragment_container, MoviesFragment()) .commit() } } }
内容的提问来源于stack exchange,提问作者Uladzislau Krukouski
相关产品推荐
相关产品推荐

