【问题标题】:Nested ViewPager returns null after rotation嵌套的 ViewPager 旋转后返回 null
【发布时间】:2014-12-23 20:17:47
【问题描述】:

我需要在PageFragSanningellerKonsekvens 中引用VerticalViewPager

我有两个 ViewPager:一个用于永远持续的水平滑动,另一个用于加载三个片段(中间、向上滑动、向下滑动)加载内容的垂直滑动。水平 ViewPager 在每次滑动时都会加载一个 VerticalViewPager 的新实例。我需要VerticalViewPager 加载的实际片段中的引用,以便我可以通过点击按钮垂直滑动。我还需要引用水平的ViewPager 以允许第一页有一个触发水平滑动的按钮。

我已经通过将引用作为这样的参数发送来解决它:

FragSanningEllerKonsekvens - 初始化VerticalViewPager的类。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.fragment_sanning_eller_konsekvens, container, false);
    initComponents();
    setComponents();
    return view;
}

private void initComponents() {
    verticalViewPager = (VerticalViewPager) view.findViewById(R.id.verticalviewpager);
    mStatementPagerAdapter = new TruthDarePagerAdapter(getChildFragmentManager()).newInstance(getChildFragmentManager(),mViewPager, verticalViewPager);
}

TruthOrDarePagerAdapter:

private ViewPager mViewPager;
private VerticalViewPager mVerticalViewPager;
public static TruthDarePagerAdapter newInstance(FragmentManager fm, ViewPager mViewPager, VerticalViewPager mVerticalViewPager){
    TruthDarePagerAdapter horizontalPagerAdapter = new TruthDarePagerAdapter(fm);
    horizontalPagerAdapter.setViewPager(mViewPager);
    horizontalPagerAdapter.setVerticalViewPager(mVerticalViewPager);
    return horizontalPagerAdapter;
}


public VerticalViewPager getVerticalViewPager() {
    return mVerticalViewPager;
}

public void setVerticalViewPager(VerticalViewPager mVerticalViewPager) {
    this.mVerticalViewPager = mVerticalViewPager;
}

private void setViewPager(ViewPager mvViewPager){
    this.mViewPager = mvViewPager;
}

private ViewPager getViewPager(){
    return mViewPager;
}

@Override
public Fragment getItem(int position) {
    PageFragSanningellerKonsekvens frag = new PageFragSanningellerKonsekvens().newInstance(getViewPager(), getVerticalViewPager());
.
.
.
    return frag;
}

PageFragSanningellerKonsekvens - 需要引用的类。

public static PageFragSanningellerKonsekvens newInstance(ViewPager mViewPager, VerticalViewPager mVerticalViewPager){
    PageFragSanningellerKonsekvens frag = new PageFragSanningellerKonsekvens();
    frag.setViewPager(mViewPager);
    frag.setVerticalViewPager(mVerticalViewPager);
    return frag;
}


private void setupMenu() {


    viewTop = view.findViewById(R.id.sek_top);
    viewBottom = view.findViewById(R.id.sek_bottom);

    viewTop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getVerticalViewPager().setCurrentItem(0, true);
        }
    });

    viewBottom.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getVerticalViewPager().setCurrentItem(2, true);
        }
    });
}

在我旋转设备之前,上面的代码运行良好。旋转后getVerticalViewPager() 返回null在应用程序的其他部分,我使用此模式没有任何问题:在旋转时,ViewPager 作为参数发送,应用程序重新加载而不会删除引用。

所以我得出的结论是 VerticalViewPager 不会在旋转时重新初始化,而 PageFragSanningellerKonsekvens 是。

我的问题是;我该如何解决?我可以强制它重新初始化,还是可以通过其他方式获得对它的引用?

编辑1:我认为它与FragmentStatePagerAdapter 中的getItem() 有关。它将被调用以在每个给定时间分配 3 个片段。我认为这可能会使getVerticalViewPager() 方法无效。

编辑 2:我移动了一些代码以允许在同一个类中初始化 ViewPager 和按钮,从而使其有点防空。感谢您的帮助!

【问题讨论】:

  • 不知道你的应用程序的“幕后”发生了什么,我个人更喜欢有一个 Activity 或 Fragment 作为维护这些东西的父级。因此不必直接传递引用并与父级“交谈”。
  • 您好!我试图在初始化其余对象的同一个片段中初始化VerticalViewPager,但它在旋转后仍然返回 null。我很惊讶,因为此时它应该重新初始化VerticalViewPager。我尝试使用单例模式(仅用于测试!),即使在完全独立的类中将其作为静态变量引用时,它也会在旋转后返回 null。
  • 我怀疑您可能在恢复过程中过早地调用它(没有使用 VerticalViewPager 的经验)。但是,如果您在 FragSanningEllerKonsekvens 有机会重新创建 UI 之前要求它,我认为它可能会返回 null。你能分别显示getViewPager()getVerticalViewPager()的代码吗?
  • 我已经在我的原始帖子@cYrixmorten 中添加了您要求的代码。实际情况可能就是这样。不过我有点困惑;因为我在每次初始化时都将VerticalViewPager 作为参数发送,所以 UI 重新创建“太快”是不是有点不可能?
  • 我不确定这些是否是我正在考虑的 sn-ps。在new PageFragSanningellerKonsekvens().newInstance(getViewPager(), getVerticalViewPager()); 中,您调用方法getViewPager()getVerticalViewPager()。我假设您在这里传递了参考资料?只是想知道 1)您如何获得这些参考资料,以及 2)您在“生命周期”的哪个时间点要求这些参考资料。

标签: java android android-fragments android-viewpager


【解决方案1】:

好的,这可能不是一个完整的答案,但我认为评论太长了。

我认为空指针发生在适配器中的 getItem 是正确的。 (确认这一点的 logcat 报告会很好)。 这样做的原因(我认为)是适配器尝试在 ViewPager 的膨胀完成之前重新创建内部片段。通常我在 onCreate 中创建类似的适配器,因为它通常不依赖于除了片段管理器之外的任何东西。

考虑到这一点,以及在当前设计中您可能很难避免使用空指针这一事实,我提出了一个新设计。

我现在只在我的手机旁,所以很难给你我想到的代码。现在我只是勾画出这个想法:

  • 将 ViewPagers 的 getter/setter 从适配器移动到 FragSanningEllerKonsekvens,让 TruthOrDarePagerAdapter 的创建只依赖于片段管理器

  • 现在对 PageFragSanningellerKonsekvens 执行相同的操作,使其成为适配器 getItem 中的 PageFragSanningellerKonsekvens.newInstance()

  • 最后,您现在在 PageFragSanningellerKonsekvens PageFragSanningellerKonsekvens 中缺少对 ViewPagers 的引用,但请记住,您现在在父级 FragSanningEllerKonsekvens 中拥有两个 ViewPagers 的 getter

所以按钮现在变成了:

((FragSanningEllerKonsekvens)getParentFragment()).getVerticalViewPager().setCurrentItem(0, true);

((FragSanningEllerKonsekvens)getParentFragment()).getVerticalViewPager().setCurrentItem(2, true);

【讨论】:

  • 谢谢!正如您之前暗示的那样,重新设计似乎是最好的解决方案,所以我做到了。现在,控制 ViewPager 的按钮在同一个片段中膨胀。感谢您的帮助!
  • 当然可以!我现在该怎么办?我应该将上面的答案标记为正确吗(因为它建议重新设计)? @cYrixmorten
  • 将重新设计提案加粗,我会将其标记为正确答案 :-) 圣诞快乐@cYrixmorten!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-04
  • 2022-12-04
  • 2020-01-15
相关资源
最近更新 更多