【问题标题】:FragmentStatePagerAdapter with ChildFragmentManager - FragmentManagerImpl.getFragment results in NullPointerException带有 ChildFragmentManager 的 FragmentStatePagerAdapter - FragmentManagerImpl.getFragment 导致 NullPointerException
【发布时间】:2013-09-05 17:53:18
【问题描述】:

编辑 2

我现在通过使用https://code.google.com/p/android/issues/detail?id=42601#c10 此处的技巧设法摆脱了错误,这就是为什么我最后一次编辑放在我的问题之上的原因。

但这导致了下一个错误:

java.lang.NullPointerException
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:569)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:211)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1281)
at android.view.View.dispatchRestoreInstanceState(View.java:12043)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2688)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2694)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2694)
at android.view.View.restoreHierarchyState(View.java:12021)
at android.support.v4.app.Fragment.restoreViewState(Fragment.java:425)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:949)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4800)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
at dalvik.system.NativeStart.main(Native Method)

现在我不知道从哪里继续......

编辑 0 - 第一个问题

我得到以下异常:

java.lang.IllegalStateException: No activity
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1091)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1877)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1492)
at android.support.v4.app._HoloFragment.performActivityCreated(_HoloFragment.java:251)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4800)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
at dalvik.system.NativeStart.main(Native Method)

我不知道从哪里开始。我正在使用最新的支持库(v4,rev18)。

在我添加 Fragment 之前一切正常,其中包含 ViewPagerFragmentStatePagerAdapter

我到处都在使用支持库,我尝试了https://code.google.com/p/android/issues/detail?id=42601的解决方案...

但还没有任何效果......

我不知道从哪里开始,有人有提示吗?

编辑 1:背景和代码

1) 在我的 MainActivity 中,我使用以下内容:

第三页有viewpager...

public void setPage(int pos, boolean addToBackStack)
 {
    Fragment nextFragment = null;
    FragmentTransaction transaction = null;

    switch (pos)
    {
        case 0:
            if (mFragmentAllRoutines == null)
                mFragmentAllRoutines = new RoutinesListFragment();
            if (!mFragmentAllRoutines.isVisible())
                nextFragment = mFragmentAllRoutines;
            break;
        case 1:
            if (mFragmentRoutine == null)
                mFragmentRoutine = new RoutineFragment();
            if (!mFragmentRoutine.isVisible())
                nextFragment = mFragmentRoutine;
            break;
        case 2:
            if (mFragmentDay == null)
                mFragmentDay = new RoutineDayFragment();
            if (!mFragmentDay.isVisible())
                nextFragment = mFragmentDay;
            break;
        default:
            break;
    }

    if (nextFragment != null)
    {
        // Fragment prevFragment = getSupportFragmentManager().findFragmentById(R.id.fragment);
        transaction = getSupportFragmentManager().beginTransaction();
        // if (prevFragment != null)
        //    transaction.detach(prevFragment);
        transaction.replace(R.id.fragment, nextFragment, nextFragment.getClass().getName());
        // transaction.attach(nextFragment);
        if (addToBackStack)
            transaction.addToBackStack(null);
        transaction.commit();
    }
}

2) 第三个片段:

这是一个带有 ViewPager 和 FragmentStatePagerAdapter 的简单 Fragment。 FragmentStatePagerAdapter 将getChildFragmentManager() 作为 FragmentManager。某处似乎存在问题。

【问题讨论】:

  • 发布您的相关代码
  • 发布您的完整堆栈跟踪、logcat 输出......以及您的代码。
  • 我更新了我的问题和我的问题的当前状态...

标签: android android-fragments android-support-library


【解决方案1】:

我需要查看更多代码才能知道在哪里应用它......但我遇到了和你类似的情况......我以同样的方式解决了 ChildFragmentManager 问题,并得到了相同的 @987654323 @,就像你一样。

我确实设法解决了它...我将尝试描述我的解决方案,就像您提供的代码一样,我不确定在哪里应用“修复”...这确实是一个修复...这不是解决这个问题的优雅方法!但是它确实对我有帮助,而且一旦我在视图寻呼机上导航离开,我就不需要恢复状态,所以对我来说没有缺点。

我有多个 Fragment,它们实现了静态代码位和 onDetach(在 https://code.google.com/p/android/issues/detail?id=42601#c10 上),每个 Fragment 都有一个寻呼机,我在 onCreateView 上附加了一个扩展 FragmentStatePagerAdapter 的适配器。

在那些适配器上,我重写了 restoreState 方法,什么都不做

    @Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
    //do nothing here! no call to super.restoreState(arg0, arg1);
}

同样,这不是最好的方法...但它确实解决了我的问题。

祝你好运!

【讨论】:

  • 为什么会出现?后果是什么?这是一个将来会解决的已知问题吗?
  • “为什么会发生?后果是什么?这是一个已知问题,将来会解决吗?” (a) 没有人知道,(b) 没有人知道,(c) 可能不知道。但这似乎对我有用。 (欢迎使用 Android)
  • 嗨 Marc 我有另一个解决方案,但是当您在片段中使用 viewpager 并在没有标签的 mainactivity 中添加片段时它可以工作
  • 当我从 FragmentPagerAdapter 切换到 FragmentStatePagerAdapter 时,我发现了这个问题,必须将此应用到 4 个视图寻呼机(MainActivity(ViewPager(fragment(ViewPager(fragment))))我会找到另一种方法,因为下面有人指出它似乎正在传递一些东西来重新创建片段,这个修复停止了,但必须有更好的方法
  • 你拯救我的一天,有一个记录
【解决方案2】:

我刚刚偶然发现了同样的问题。

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
     at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:873)
     at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:215)

Marc 的解决方案有效,但在我的情况下,它导致 FragmentStatePagerAdapter 的 Fragment 滞后。所以我覆盖了称为 super 的 restoreState,将它包装在 try/catch 中,并且它没有延迟。

@Override
public void restoreState(Parcelable state, ClassLoader loader) {
    try{
        super.restoreState(state, loader);
    }catch (NullPointerException e){
        // null caught
    }
}

更新:

从那时起,我一直在生产中使用此解决方案。所以使用起来很安全。

【讨论】:

  • 不知道问题出在哪里,但这个答案解决了它!谢谢
  • 我不知道这是否会以某种深刻而神秘的方式对应用程序有害。但我愿意尝试一下。
  • 这也修复了 ViewPager 的错误:java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.util.SparseArray.get(int)' on an null object reference子片段不起作用。 1. childFragmentManager used; 2. without addToBackStack(null)
  • 这对我有用。从 NavigationView 在我的应用程序中导航并按下后退按钮时出现问题。干得好。
【解决方案3】:

在我这边,我在包含片段中保留了对 ViewPager 片段的引用,并使用 onSaveInstanceState 来存储它们的状态。 我认为发生 NPE 是因为这与 ViewPager 自己的恢复片段的机制发生冲突。我所做的是将我的架构从 ViewPager 更改为我自己管理的片段事务。 (ViewPager 不适合我的情况)

【讨论】:

    【解决方案4】:

    首先,英语不是我的母语,如果我语法有问题,请告诉我。 我在我的项目中遇到了这个问题。起初我按照 Marc 所说的做了,而且效果很好。但是当我在父片段中添加另一个 ViewPager 时,无论在这个新的 viewpager 中使用什么样的代码,新的 ViewPager 都与旧的 ViewPager 显示相同。 最后我找到了原因。我们总是使用 FragmentTrasaction.replace(R.layout.fragment,fragment) 方法创建 Fragment。因此,我们在使用此方法时会创建一个新的片段实例。我没有使用 replace() 方法,而是使用 FragmentTransaction.hide() 和 show() 方法来切换片段。我以这种方式解决了我的问题。 这是我的代码 sn-ps :

    @Override
    public void onClick(View v) {
        FragmentTransaction transaction = fm.beginTransaction();
        switch (v.getId()) {
            case R.id.tv_schedule_day:
            hideFragment(transaction);
            if (dayFragment == null) {
                dayFragment = new ScheduleDayFragment();
                transaction.add(R.id.ll_schedule_content, dayFragment);
            } else {
                transaction.show(dayFragment);
            }
            transaction.commit();
            break;
            case R.id.tv_schedule_week:
            hideFragment(transaction);
            if (weekFragment == null) {
                weekFragment = new ScheduleWeekFragment();
                transaction.add(R.id.ll_schedule_content, weekFragment);
            } else {
                transaction.show(weekFragment);
            }
            transaction.commit();
            break;
        case R.id.tv_schedule_month:
            hideFragment(transaction);
            if (monthFragment == null) {
                monthFragment = new ScheduleMonthFragment();
                transaction.add(R.id.ll_schedule_content, monthFragment);
            } else {
                transaction.show(monthFragment);
            }
            transaction.commit();
            break;
    
    private void hideFragment(FragmentTransaction transaction) {
        if (dayFragment != null) {
            transaction.hide(dayFragment);
        }
        if (weekFragment != null) {
            transaction.hide(weekFragment);
        }
        if (monthFragment != null) {
            transaction.hide(monthFragment);
        }
    }
    

    我使用 hide() 和 show() 方法来制作 switch 父片段,所以当我在嵌入片段中使用 getChildFragmentManager() 时,它不会返回 null。 这个问题是2013年问的,我想没有人会看到这个答案,但我还是很高兴回答这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-13
      • 2016-03-07
      • 2017-05-16
      • 1970-01-01
      • 2014-06-09
      • 2015-11-07
      • 1970-01-01
      相关资源
      最近更新 更多