SMG*_*ost 17 android android-viewpager
我有一个在 FragmentStateAdapter 中有多个片段的 viewpager2。每当我尝试打开一个新片段,然后使用 viewpager2 返回到当前片段时,都会出现异常:
Expected the adapter to be 'fresh' while restoring state.
Run Code Online (Sandbox Code Playgroud)
FragmentStateAdapter 似乎无法正确恢复其状态,因为它期望它为空。
我能做些什么来解决这个问题?
我在 ViewPager2 中遇到了同样的问题。经过大量努力测试不同的方法,这对我有用:
public void onExitOfYourFragment() {
viewPager2.setAdapter(null);
}
Run Code Online (Sandbox Code Playgroud)
当你再次回到片段时:
public void onResumeOfYourFragment() {
viewPager2.setAdapter(yourAdapter);
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是我在 Fragment 类字段中创建了 FragmentStateAdapter,它只创建了一次。所以当我的 onCreateView 第二次被调用时,我遇到了这个问题。如果我在每次 onCreateView 调用上重新创建适配器,它似乎工作。
此适配器/视图可用作 FragmentStatePagerAdapter 的替代品。
如果您寻求的是在从 Backstack 重新进入时保留片段,那么使用此适配器将很难实现。
球队设置了很多休息点来防止这种情况发生,只有天知道为什么......
他们本可以使用一个自分离的生命周期观察者,这种能力已经在其代码中预见到了,但在 Android 架构中没有任何地方使用这种能力......
他们应该使用这个未完成的组件来监听全局 Fragments 生命周期而不是 viewLifeCycle,从这里开始,我们可以将监听从 Fragment 扩展到 viewLifeCycle。(附加/分离 viewLifeCycle 观察者 ON_START/ON_STOP)
其次...即使这样做了,viewPager 本身是建立在 recyclerView 之上的,这一事实使得处理您所期望的 Fragment 行为变得极其困难,这是一种保存状态,一次性实例化,以及明确定义的生命周期(可控/预期销毁)。
该适配器的功能是矛盾的,它检查 viewPager 是否已经提供了 Fragments,同时在重新进入时仍然需要一个“新鲜”适配器。
它在退出到 backStack 时保留片段,同时期望在重新进入时重新创建所有片段。
假设所有其他变量已经考虑到正确的 viewLifeCycle 处理(注册/取消注册以及设置和重置参数),则防止字段实例化适配器的中断是:
@Override
public final void restoreState(@NonNull Parcelable savedState) {
if (!mSavedStates.isEmpty() || !mFragments.isEmpty()) {
throw new IllegalStateException(
"Expected the adapter to be 'fresh' while restoring state.");
}
.....
}
Run Code Online (Sandbox Code Playgroud)
第二次休息:
@CallSuper
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
checkArgument(mFragmentMaxLifecycleEnforcer == null);
mFragmentMaxLifecycleEnforcer = new FragmentMaxLifecycleEnforcer();
mFragmentMaxLifecycleEnforcer.register(recyclerView);
}
Run Code Online (Sandbox Code Playgroud)
其中 mFragmentMaxLifecycleEnforcer 在重入时必须为 == null,否则会在 checkArgument() 中引发异常。
第三:在重新进入(到视图,从后台堆栈)时放置一个片段垃圾收集器,该收集器在 10 秒后延迟,试图销毁屏幕外片段,导致所有屏幕外页面上的内存泄漏,因为它杀死了控制其各自的 FragmentManager。生命周期。
private void scheduleGracePeriodEnd() {
final Handler handler = new Handler(Looper.getMainLooper());
final Runnable runnable = new Runnable() {
@Override
public void run() {
mIsInGracePeriod = false;
gcFragments(); // good opportunity to GC
}
};
mLifecycle.addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
handler.removeCallbacks(runnable);
source.getLifecycle().removeObserver(this);
}
}
});
handler.postDelayed(runnable, GRACE_WINDOW_TIME_MS);
}
Run Code Online (Sandbox Code Playgroud)
所有这些都是因为它的罪魁祸首:构造函数:
public FragmentStateAdapter(@NonNull FragmentManager fragmentManager,
@NonNull Lifecycle lifecycle) {
mFragmentManager = fragmentManager;
mLifecycle = lifecycle;
super.setHasStableIds(true);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4613 次 |
| 最近记录: |