ViewPager + Fragment + savedInstanceState
Posted
技术标签:
【中文标题】ViewPager + Fragment + savedInstanceState【英文标题】:ViewPager + Fragment + saveInstanceState 【发布时间】:2014-03-03 14:49:32 【问题描述】:我有一个包含 ViewPager 的简单 Activity,它显示 Fragments。
我的 Activity 应该显示有关足球联赛的信息,并且每个片段都显示诸如 livescroes/matchdays、table 等信息。
我启动 Activity 时使用的 Intent,包含联赛 ID。
并且每个 Fragment 都需要这个联赛 id 来加载正确的数据。
所以我的 FragmentPagerAdapter 看起来像这样
public class LeaguePagerAdapter extends FragmentPagerAdapter
private String leagueId;
public LeaguePagerAdapter(FragmentManager fm, String leagueId)
super(fm);
this.leagueId = leagueId;
@Override
public Fragment getItem(int pos)
if (pos == 0)
return TableFragment.newInstance(leagueId);
else
return MatchdayFragment.newInstance(leagueId);
TableFragment 看起来像这样(比赛日片段看起来很相似):
public class TableFragment extends PullToRefreshListViewAdFragment
private String leagueId;
public static TableFragment newInstance(String leagueId)
TableFragment t = new TableFragment();
t.leagueId = leagueId;
return t;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
// Setup UI and load data
有时 LeagueId 为空。我在崩溃日志中看到了异常(crittercism)。但我问自己为什么。在我看来,问题在于活动在后台被破坏并在(例如)用户使用多任务按钮切换到我的应用程序时重建。
据我所知,如果 Activity 已被销毁,原始 Intent 将由 android 自身存储在内部。因此,我没有在我的活动和片段中实现任何 onSaveInstanceState() 。在我的活动中,我阅读了 Intent Extra 以检索leagueId。这工作正常,也可以恢复活动。我假设通过重新创建活动,将创建一个新的 LeaguePagerAdapter,并且所有片段也将被新创建。
正确吗?还是“旧”片段实例将被恢复,因此 LeagueId 为空(因为片段没有将 LeagueId 存储在 Fragments 的 onSaveInstanceState 方法中?)。
有没有办法测试这种生命周期的东西
【问题讨论】:
【参考方案1】:之所以为null,是因为系统使用默认构造函数恢复Fragment。文件是这样说的:
每个片段都必须有一个空的构造函数,因此可以在恢复其活动状态时对其进行实例化。强烈建议子类不要有其他带参数的构造函数,因为片段重新实例化时不会调用这些构造函数;相反,参数可以由调用者使用 setArguments(Bundle) 提供,然后由 Fragment 使用 getArguments() 检索。
编辑:另外,看看这个:Fragment's onSaveInstanceState() is never called
编辑:为了进一步添加,您正在使用 newInstance(String)
方法创建片段。如果您的 Fragment 被 Android 杀死,它会使用默认构造函数,因此不会设置您的 leagueId
变量。尝试使用 setArguments
/getArguments
将值传递到您的 Fragment 中。
【讨论】:
所以我的假设,一个完整的新片段将被实例化是错误的?而 setArguments() 设置的 Arguments 会通过销毁 Fragment 自动保存? @sockeqwe 如果您使用setArguments
而不是像您那样直接进行字段操作,那么据我所知(从我看到的其他答案),系统将在重新创建您的片段时再次使用这些相同的参数.现在的问题是您使用newInstance
实例化您的片段,然后在该方法中设置字段。 Android 在重新创建时不使用newInstance
。因此,尝试使用newInstance
内部的setArguments
将leagueId
传递给您的片段,看看是否可行。要进行测试,您可以尝试更改方向或使用 DDMS 终止您的进程。
当然,如果您使用setArguments
,那么您必须使用getArguments
检索值。
我将使用 onSaveInstanceState(),因为我可以使用 Annotations 来保存我的值,或者您知道使用 setArguments() 而不是 onSaveInstanceState() 的优点/缺点吗?
@sockeqwe 使用 setArguments()
是初始化 Fragment 的正确方法,所以我建议这样做。我建议不要使用onSaveInstanceState()
,因为它有不同的目的并且会导致意想不到的副作用。有趣的是,谷歌刚刚在他们的 Google Plus 社区上发布了一篇关于此的帖子:plus.google.com/108967384991768947849/posts/bCD7Zvd945d以上是关于ViewPager + Fragment + savedInstanceState的主要内容,如果未能解决你的问题,请参考以下文章