我在FragmentStateAdapter中有一个带有多个片段的viewpager2。每当我尝试打开一个新片段,然后使用viewpager2返回到当前片段时,都会出现异常:
Expected the adapter to be 'fresh' while restoring state.
似乎FragmentStateAdapter无法正常恢复其状态,因为它期望它为空。
该如何解决?
答案 0 :(得分:1)
所以我的问题是我在我的Fragment类字段中创建了FragmentStateAdapter,在该字段中它只创建了一次。所以当我的onCreateView被第二次调用时,我遇到了这个问题。如果我在每个onCreateView调用上重新创建适配器,那么它似乎可以正常工作。
答案 1 :(得分:1)
我在ViewPager2中遇到了同样的问题。经过大量测试不同方法的努力,这对我有用:
public void onExitOfYourFragment() {
viewPager2.setAdapter(null);
}
当您再次回到片段时:
public void onResumeOfYourFragment() {
viewPager2.setAdapter(yourAdapter);
}
答案 2 :(得分:1)
可以通过viewPager2.isSaveEnabled = false
答案 3 :(得分:0)
在片段中使用ViewPager2时,我也得到了这个java.lang.IllegalStateException: Expected the adapter to be 'fresh' while restoring state.
。
似乎是因为我在 onCreateView()方法中执行mViewPager2.setAdapter(mFragmentStateAdapter);
。
我通过将mViewPager2.setAdapter(mMyFragmentStateAdapter);
移至我的 onResume()方法来对其进行了修复。
答案 4 :(得分:0)
我通过测试是否等于null来解决了这个问题
if(recyclerView.adapter == null) {recyclerView.adapter = myAdapter}
答案 5 :(得分:0)
我一直在为此苦苦挣扎,以前的答案都没有帮助。
这可能不适用于所有可能的情况,但是在我的情况下,包含ViewPager2的片段是固定的,很少。我通过使用FragmentTransaction的show()
和{{1}进行片段切换来解决此问题。 }方法,而不是通常为此推荐的hide()
方法。将replace()
应用于活动片段,并将show()
应用于所有其他片段。这样可以避免重新创建视图以及还原触发问题的状态之类的操作。
答案 6 :(得分:0)
此适配器/视图可用于替代FragmentStatePagerAdapter。
如果您要保存的片段是从Backstack重新进入的,那么使用此适配器将很难实现。
为了防止这种情况,团队安排了许多休息时间,只有上帝知道原因...
他们本可以使用自分离的lifeCycle观察器,该功能已经在其代码中预见到,但是android体系结构中没有地方使用该功能...。
他们应该使用这个未完成的组件来监听全局Fragments生命周期,而不是它的viewLifeCycle,从现在开始,人们可以将监听范围从Fragment扩展到viewLifeCycle。 (附加/分离viewLifeCycle观察者ON_START / ON_STOP)
第二...即使这样做,viewPager本身是建立在recyclerView之上的事实,使得处理片段行为的期望极其困难,这是一种保存状态,时间实例化和明确定义的生命周期(可控/预期破坏)。
此适配器在功能上是矛盾的,它检查viewPager是否已经提供了Fragments,同时在重入时仍需要“新鲜”适配器。
它在退出BackStack时保留片段,同时希望在重新进入时重新创建所有片段。
为防止字段实例化适配器而进行的中断(假设已所有个其他变量已为适当的viewLifeCycle处理(参数的注册/注销和设置及重置)进行了说明)
{
"_index": "64898361",
"_type": "_doc",
"_id": "1",
"_version": 8,
"_seq_no": 13,
"_primary_term": 1,
"found": true,
"_source": {
"survey_id": 15,
"submission_id": 12069,
"account_id": 2,
"answers": [
{
"answer_txt": "happy",
"question_id": 153,
"skipped": false
}
],
"id": "15_12069"
}
}
第二次休息:
@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.");
}
.....
}
其中mFragmentMaxLifecycleEnforcer在重入时必须为== null,否则会在checkArgument()中引发异常。
第三: 重新进入(到视图,从从后栈返回)时放置的Fragment垃圾收集器在10秒后被延迟,试图破坏屏幕上的碎片,从而导致内存泄漏所有屏幕外的页面,因为它会杀死控制其生命周期的各自的FragmentManager。
@CallSuper
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
checkArgument(mFragmentMaxLifecycleEnforcer == null);
mFragmentMaxLifecycleEnforcer = new FragmentMaxLifecycleEnforcer();
mFragmentMaxLifecycleEnforcer.register(recyclerView);
}
所有这些都是由于其主要罪魁祸首:构造函数:
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);
}
答案 7 :(得分:0)
我遇到了同样的问题。
经过一番研究,我发现它与 Adapter
的实例有关。当它被创建为 Fragment
的惰性属性时,它会因该错误而崩溃。
因此在 Adapter
中创建 Fragment::onViewCreated
可以解决它。