(Fragment六)ViewPager2 与 Fragment 结合时,FragmentStateAdapter 和 FragmentAdapter 的区别?它们的生命周期有何不同?

ViewPager2是Android Jetpack中对旧ViewPager的现代化替代,它与Fragment结合使用时,其核心适配器FragmentStateAdapterFragmentAdapter内存管理策略生命周期控制上有着根本性的区别。这些区别直接影响到应用的性能和内存占用。”


核心区别:内存管理哲学

首先,我们通过一个表格来快速把握两者的核心差异:

特性 FragmentStateAdapter FragmentAdapter
设计目标 处理大量页面,优化内存使用 处理少量静态页面,保持所有页面活跃
页面管理 销毁不可见页面,只保存其状态 保留所有页面实例在内存中
状态保存 自动调用onSaveInstanceState()保存状态,并在页面重新创建时恢复 依赖Fragment自身在内存中的存活,无特殊状态恢复机制
适用场景 图片浏览器、新闻Feed流、多步骤表单等页面数量多或不确定的场景 固定的Tab页面(如3-5个),且每个页面都需要保持其UI状态(如滚动位置、输入内容)
内存开销 (仅保留少量页面实例) (所有页面实例常驻内存)

工作原理与生命周期深度剖析

为了更直观地理解这两种适配器对Fragment生命周期的管理差异,下图展示了它们在页面切换时的不同行为:

Android 开发中,`Fragment` `ViewPager2` 的生命周期交互是一个复杂且容易出错的领域,尤其是在处理滑动缓存机制。以下是关于 `Fragment` `ViewPager2` 生命周期交互的详细分析: ### Fragment ViewPager2生命周期交互 `ViewPager2` 是基于 `RecyclerView` 实现的,因此其内部的 `Fragment` 管理依赖于 `RecyclerView` 的回收机制缓存策略。`ViewPager2` 中的每个页面通常是一个 `Fragment`,其生命周期 `RecyclerView` 的 `ViewHolder` 生命周期密切相关。 当 `ViewPager2` 展示第一个页面,`RecyclerView` 会调用 `onCreateViewHolder` `onBindViewHolder` 方法,此对应的 `Fragment` 会经历其完整的生命周期,包括 `onCreate`、`onCreateView`、`onStart` `onResume` 等阶段。`Fragment` 绑定的 `View` 会被添加到 `RecyclerView` 的子项中[^2]。 当用户滑动到第二个页面,`RecyclerView` 会将第一个页面的子项放入一级缓存中,此并不会销毁第一个页面的 `Fragment`。这意味着第一个页面的 `Fragment` 仍然处于活动状态,但其 `View` 已经从屏幕上移除。 当用户再次滑动回第一个页面,`RecyclerView` 只需要重新将缓存中的子项添加到屏幕上,而不会再次触发 `Fragment` 的生命周期回调。这使得页面切换更加流畅,因为不需要重新创建绑定 `Fragment`。 当用户滑动到后面的页面,如果一级缓存已满,`RecyclerView` 会将超出缓存范围的页面放入三级缓存中,并触发子项的回收。此,对应的 `Fragment` 会经历销毁流程,包括 `onPause`、`onStop` `onDestroyView` 等生命周期方法。 `ViewPager2` 提供了一个方法 `setOffscreenPageLimit`,用于设置屏幕外的页面缓存数量。通过调整这个值,可以控制 `ViewPager2` 中页面的预加载缓存行为。默认情况下,`ViewPager2` 会预加载一个页面,这意味着即使用户没有滑动到下一个页面,该页面的 `Fragment` 也会被创建并绑定,但其 `View` 不会被添加到屏幕上,因此不会触发 `Fragment` 的生命周期回调。 ### 示例代码 以下是一个简单的 `ViewPager2` `FragmentStateAdapter` 的示例代码: ```java public class MyFragmentPagerAdapter extends FragmentStateAdapter { public MyFragmentPagerAdapter(@NonNull FragmentActivity fragmentActivity) { super(fragmentActivity); } @NonNull @Override public Fragment createFragment(int position) { // 根据位置返回相应的Fragment return MyFragment.newInstance(position); } @Override public int getItemCount() { // 返回页面总数 return 3; } } ``` 在 `MyFragment` 类中,可以重写生命周期方法以观察其行为: ```java public class MyFragment extends Fragment { private static final String ARG_POSITION = "position"; public static MyFragment newInstance(int position) { MyFragment fragment = new MyFragment(); Bundle args = new Bundle(); args.putInt(ARG_POSITION, position); fragment.setArguments(args); return fragment; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); int position = getArguments().getInt(ARG_POSITION); Log.d("MyFragment", "onCreate: " + position); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_my, container, false); int position = getArguments().getInt(ARG_POSITION); TextView textView = view.findViewById(R.id.text_view); textView.setText("Fragment " + position); return view; } @Override public void onResume() { super.onResume(); int position = getArguments().getInt(ARG_POSITION); Log.d("MyFragment", "onResume: " + position); } @Override public void onPause() { super.onPause(); int position = getArguments().getInt(ARG_POSITION); Log.d("MyFragment", "onPause: " + position); } @Override public void onDestroyView() { super.onDestroyView(); int position = getArguments().getInt(ARG_POSITION); Log.d("MyFragment", "onDestroyView: " + position); } } ``` ### 总结 `ViewPager2` `Fragment` 的生命周期交互主要依赖于 `RecyclerView` 的回收机制缓存策略。通过理解这些机制,可以更好地管理页面的创建、销毁缓存,从而提高应用的性能用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值