尝试在空对象引用上调用虚拟方法'android.support.v4.app.FragmentHostCallback.getHandler()'

29

我的应用程序由4个作为选项卡加载在一个父Fragment中使用FragmentPagerAdapter的片段组成。

问题是,当我运行应用程序并按返回键后重新打开应用程序时,我会收到这个错误日志:

FATAL EXCEPTION: main
java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Handler android.support.v4.app.FragmentHostCallback.getHandler()' on a null object reference
    at android.support.v4.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:1949)
    at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1965)
    at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:620)
    at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143)
    at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:513)
    ...

父Fragment中的代码行为:

viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);

同时ViewPageAdapter都不为空!!

需要提到的是,我所有的Fragment生命周期都已经被管理好了,但是空值问题却发生在适配器内部!当我使用Activity作为父级而不是Fragment时,同样的适配器可以正常工作!!!

9个回答

38
经过大量研究,看起来这是一个支持库问题:

具有片段和ViewPager的Activity在配置更改时崩溃
Android支持库问题24.1.0

我还发现了这个答案,但它似乎很不寻常要将一个标志添加到我的代码中:

尝试在空对象上调用虚拟方法'android.os.Handler android.support.v4.app.FragmentHostCallback.getHandler()'

我像这样覆盖了我的FragmentPagerAdapter的finishUpdate方法,目前问题得到了解决!
@Override
public void finishUpdate(ViewGroup container) {
    try{
        super.finishUpdate(container);
    } catch (NullPointerException nullPointerException){
        System.out.println("Catch the NullPointerException in FragmentPagerAdapter.finishUpdate");
    }
}

还有更好的答案吗?请告诉我...


1
我面临着同样的问题,我将尝试这个修复方法,直到官方发布正式修复。 - Firas Al Mannaa
很高兴能够帮到你 :) - Mohsen Mirhoseini
1
适用于我...谢谢。 - Manoj
1
它对我不起作用。有更好的解决方案吗?请告诉我。 - aslamhossin
1
这个可行!谢谢你为此节省了更多的工作时间。 :) - Chinibin
2
这种情况我也遇到过一次,但是现在复现不了。你怎么能够复现它呢? - Maor Hadad

16

我在我的项目中也遇到了相同的问题。但这是我的错。

为什么会出现这种情况?

我在回调函数中调用了onBackPressed(),此时activity已经调用了onDestroy()方法;

由于FragmentManager中的mHost实例在调用onDestroy()后被设置为null,所以当再次调用onBackPressed()时,它将再次使用mHost实例。


10
@Override
public void onBackPressed() {
//     super.onBackPressed();
       finish();
}  

重写活动中的 onBackPressed 方法。
移除 super 调用:super.onBackPressed
并调用 finish。


你确定它会工作吗?我有时会因为onBackPressed()而出现错误。 - Bolt UIX
完全不知道为什么(从技术上讲)...但它有效!!!+1 - ekashking

4

我知道可能有些晚了,但这是我的一个愚蠢错误,我没有立即看清:

@Override
public void onStop() {
    super.onDestroy(); //I was calling the wrong super
}

3

我曾经遇到过相同的问题,导致问题的原因是在不同的fragment实例中重用了ViewPager实例。解决方案是在fragment的onDestroyView()方法中将适配器设为null。

@Override public void onDestroyView() {
    mViewPager.setAdapter(null);
    super.onDestroyView();
}

这里可以查看展示了问题及解决方案的项目链接.


3

我也遇到了同样的问题。在我的情况下,问题是我没有注意到上一次打开时重复使用了适配器。

我查看了发送异常的FragmentManager.java类,并且在崩溃的同一行中发现了以下内容:"必须从片段宿主的主线程调用"

我的代码如下:

PagerAdapter adapter = MPageAdapter.getInstance(getSupportFragmentManager()); 
viewPager.setAdapter(adapter);

因为我使用了PageAdapter作为片段之间通信的桥梁,所以我使用了单例模式。这对我很有效,但是一旦我在另一个活动中重复了这个结构,我遇到了相同的异常。原因是我忘记在每次使用结束时销毁适配器类的单例。

@Override
protected void onDestroy() {
    MPageAdapter.Destroy();  //I forgot this one, that makes singleton = null;
    super.onDestroy();
}

2

我通过在我的ActivityonBackPressed()方法中添加!isFinishing来解决了这个问题。

override fun onBackPressed() {
        if (!isFinishing) {            
            super.onBackPressed()
            // your implementation specific code here..
        }
    }

在我的情况下,问题出现在一些代码流程中,我的DialogFragment在调用finish()后立即调用其父ActivityonBackPressed(),导致了此崩溃。希望这能帮助仍在寻找答案的人!

0

我之前使用了错误的活动引用来获取

getSupportFragmentManager()

使用正确的活动引用修复了我的崩溃问题。


0

只需注释掉 super.onBackPressed() 方法,然后写入 finish()

@Override
public void onBackPressed() {
//     super.onBackPressed();
       finish();
}  

在我的情况下,这个方法有效!


它可能会起作用,但这是一个无意义的答案,因为您正在覆盖“onBackPressed”行为,而您可以轻松地调用“finish()”而不是使用backpressed方法。 - Hanako

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接