我遇到了崩溃,如果android操作系统杀死了一个进程,当应用程序尝试从保存的实例重建活动和片段时,我的recyclerview的适配器始终为空。
这是我的等级:
Parent Activity // destroyed when process is killed
Nested View Pager Fragment // view pager containing four recycler view fragments
Recycler Frag 1
Recycler Frag 2
Recycler Frag 3
Recycler Frag 4
这些回收站片段中的每个片段都是完全相同的片段,除了,当父活动创建它们的新实例时,我调用了一个公开的setter方法,该方法设置了一个RecyclerView.Adapter类型的适配器(原因是每个碎片可能是回收站,但其显示的内容以及用户与之交互的方式可能有所不同)来自父活动的示例代码:
RecyclerFrag feedFrag = RecyclerFrag.newInstance();
feedFrag.setAdapter(new myCustomAdapter());
现在,我的最终用户遇到了崩溃,在该崩溃中,如果他们将此活动作为背景,并且操作系统决定终止该活动所持续的进程,它将无法正确恢复自身。从我看到的内容来看,除了适配器为null以外,所有内容都在还原中。然后,代码尝试访问适配器接口,并因NPE而崩溃。
我不知道为什么会这样。我还试图将精力放在恢复此类事件中的活动和片段上。我已经阅读了许多有关状态恢复的帖子和文档,但仍然找不到解决方案。这是我尝试过的解决方案示例,也许有人可以指出我的逻辑上的缺陷/差距。
让回收站碎片将其自身存储在fragmentManager中,并尝试在onActivityCreated方法调用中将其读回。
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
getFragmentManager().putFragment(outState, "myFrag", this);
...
}
然后:
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(savedInstanceState != null) {
getFragmentManager().getFragment(savedInstanceState, "myFrag");
...
}
}
对我来说,这感觉像是我错过了标记。片段获取对自身的引用然后尝试从中进行设置是没有意义的。更糟糕的是,它返回的片段具有空适配器。生活和学习。
接下来,我尝试将在父活动中创建的片段保存为viewPager实现,然后尝试在父onCreate中还原这些片段。父类如下所示:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "frag1", frag1);
...
}
然后:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
getSupportFragmentManager.getFragment(savedInstanceState, "myFrag);
...
}
}
关于这种方法,值得注意的是,当我使用onSaveInstance
方法将片段保存到管理器时,我的adpater不为null,这很有意义。当我在onCreate方法中抓住它时,该片段适配器现在为空。
这使我最后的想法是,也许恢复适配器效率不高,因此不应该这样做。再说一次,对我而言,在Recycler片段内创建适配器没有意义,因为我希望该片段采用RecyclerView.Adapter
类型的任何适配器实现。对于进一步的上下文,viewPager实现的类型为FragmentStatePagerAdapter
,它提供了最小的方法来覆盖使其运行。据我了解,这正是您应该做的,父级FragmentStatePagerAdapter
将为您处理其余的恢复过程。我在这个假设上错了吗?
非常感谢您对此事的任何投入。但是,我试图提供尽可能多的信息,如果您觉得可以为我提供更多信息,可以帮助我,如果您让我知道,我将很乐意更新我的帖子。谢谢!
最终编辑: 我最终找到了与该帖子标记为答案的解决方案相似的解决方案。我将在下面提供我的实际解决方案,以便将来任何人发现此帖子对他们的情况有所帮助。
CAR_PREVIEW_SEARCH
或CAR_PREVIEW_SELECTABLE
之类的枚举在onCreateView
答案 0 :(得分:2)
在没有看到更多代码基础的情况下,我不能自信地解决您的实际问题,但是以下几行令人担忧;
这些回收站碎片中的每个碎片都是完全相同的碎片 除了,当父活动创建它们的新实例时,我 调用设置类型适配器的公开的setter方法 RecyclerView.Adapter
我可以建议另一种设置类型的方法吗?
在您的FragmentStatePagerAdapter
中创建各种片段类型的枚举;
public enum Page {
PAGE_ONE,
PAGE_TWO,
PAGE_THREE
}
然后在您的getItem(int position)
实现中;
@Override
public Fragment getItem(int position) {
CustomFragment fragment = CustomFragment();
Bundle bundle = new Bundle();
bundle.putInt(CustomFragment.INDEX, position); // You could swap this to whatever serialised information you need
fragment.setArguments(bundle);
return fragment;
}
在CustomFragment的onCreateView
实现中,您可以像这样访问此捆绑包;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.custom_fragment, container, false);
RecyclerView.Adapter adapter;
if(getArguments() != null) {
switch (FragmentStatePagerAdapter.Page.values()[getArguments().getInt(CustomFragment.INDEX)]) {
// Assign whatever adapter/values ect in here
}
} else {
// setup various default states here
adapter = SomeDefaultCustomFragmentAdapter()
}
// set adapters etc
return view;
}
以上内容确保仅在确实有视图时才操作适配器。当系统重新创建片段时,所有内容都应正常运行。
希望这至少有所帮助。