在使用ViewPager时,NPE在Fragment.setUserVisibleHint()中

我对此感到不知所措。 我在ViewPager中手动切换选项卡。 我有这个代码在我的活动:

@Override public void onBackPressed() { if (childFragmentStack.empty()) { // Go to the devices screen Intent intent = new Intent(this, SelectDeviceActivity.class); startActivity(intent); } else { Fragment fragment = childFragmentStack.pop(); if (fragment == null) { return; } processingBackStack = true; if (fragment instanceof ViewChildFragment) { viewFragment.activateFragment((ViewChildFragment) fragment); mViewPager.setCurrentItem(VIEW_FRAGMENT_INDEX, true); } else if (fragment instanceof SetupChildFragment) { setupFragment.activateFragment((SetupChildFragment) fragment); mViewPager.setCurrentItem(SETUP_FRAGMENT_INDEX, true); //** } else if (fragment == homeFragment) { mViewPager.setCurrentItem(HOME_FRAGMENT_INDEX, true); //** } processingBackStack = false; } } 

如果我在选项卡之间滚动,我将它们添加到堆栈('childFragmentStack')。 我正在使用FragmentPagerAdapter来处理片段。 会发生什么事是,如果我做了像查看 – >设置 – >查看 – >设置,然后扭转它,它只能达到设置 – >查看 – > CRASH。 这就像当我按回来安装片段不再是有效的我在做什么,但它永远不会重新创build! 安装片段只在MainActivity.onCreate()中创build,所以它应该仍然是有效的。

NPE发生在我标记**的行上。 这是完整的堆栈跟踪:

  04-18 16:04:57.096: E/AndroidRuntime(13072): FATAL EXCEPTION: main 04-18 16:04:57.096: E/AndroidRuntime(13072): java.lang.NullPointerException 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.app.Fragment.setUserVisibleHint(Fragment.java:841) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem(FragmentPagerAdapter.java:130) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.view.ViewPager.populate(ViewPager.java:1066) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:550) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:509) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:501) 04-18 16:04:57.096: E/AndroidRuntime(13072): at com.lochinvar.serf.MainActivity.onBackPressed(MainActivity.java:234) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.app.Activity.onKeyUp(Activity.java:2131) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.view.KeyEvent.dispatch(KeyEvent.java:2633) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.app.Activity.dispatchKeyEvent(Activity.java:2361) 04-18 16:04:57.096: E/AndroidRuntime(13072): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1819) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3577) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3547) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2797) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.os.Handler.dispatchMessage(Handler.java:99) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.os.Looper.loop(Looper.java:137) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.app.ActivityThread.main(ActivityThread.java:4745) 04-18 16:04:57.096: E/AndroidRuntime(13072): at java.lang.reflect.Method.invokeNative(Native Method) 04-18 16:04:57.096: E/AndroidRuntime(13072): at java.lang.reflect.Method.invoke(Method.java:511) 04-18 16:04:57.096: E/AndroidRuntime(13072): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 04-18 16:04:57.096: E/AndroidRuntime(13072): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 04-18 16:04:57.096: E/AndroidRuntime(13072): at dalvik.system.NativeStart.main(Native Method) 

[编辑]我忘了提及我重覆FragmentPagerAdapter.getPageTitle(),它永远不会返回空(默认情况下去一个string)。

Solutions Collecting From Web of "在使用ViewPager时,NPE在Fragment.setUserVisibleHint()中"

最后! 我现在能够可靠地重新创build这个错误!

我发现重新创build错误的另一种方法是closuresactivity / app,然后用ViewPager片段快速重新打开页面。 您可能需要尝试几次,因为在我的testing中,我不得不在30毫秒内重新打开应用程序。 对于不同的速度设备,这个时间可能会更慢或更快。

问题是,我只明确创build了一个片段(使用new ),并保持对该实例的引用,以便我可以重用它。 对这个问题的一个简单的解决方法是总是返回Fragment的new实例FragmentPagerAdapter.getItem(...) ,如下所示。

 public class ViewPagerAdapter extends FragmentPagerAdapter { ... @Override public Fragment getItem(int position) { switch (position) { case 0: return mMyFragment; // Error. Has the edge-case crash. case 1: return new MyFragment(); // Works. default: return new MyDefaultFragment(); } } } 

ps – 根本问题可能与Fragment生命周期有关,并试图在被破坏时再次使用它。

pps – 这个解决scheme修复了android.app.Fragment.setUserVisibleHint(Fragment.java:997)的NullPointerException,也应该为android.support.v4.app.Fragment.setUserVisibleHint工作。

这对我来说是一个真正的扭曲。 我们删除了代替Fragment的所有代码,并在Activity的整个生命周期中保留了相同的片段,并且仍然存在这个问题。 直到我们viewPager.setOffscreenPageLimit(TABS); TABS是我们停止得到引用的NullPointerException的选项卡数量(在我们的例子中是4)。

FWIW – 我很确定问题出在Google的代码中。 我们无法在运行Nexus 5的棒棒糖上失败,但在运行Kitkat的三星设备上失败。 当我追踪到错误本身时,看起来发生了故障,因为被引用的Fragment已经经历了内部的Fragment.initState函数,因为Fragmentid是-1。

即使使用了FragmentStatePagerAdapter,我也遇到了非常相似的情况( Fragment.setUserVisibleHintexception)。 当底层数据发生变化时,我的应用程序崩溃了(因此很难重现)。

在我的情况下,我终于能够通过覆盖适配器中的以下方法来摆脱此崩溃:

 @Override public void restoreState(Parcelable state, ClassLoader loader) { // don't super ! } 

我认为在这个类中存在一个bug,因为在StackOverflow中有类似的问题。

我希望这可能对某人有用。

编辑:我发布了类似的答案android.support.v4.app.Fragment.setUserVisibleHint空指针在应用程序恢复然而,我不是肯定的确定,这些问题是重复的。 不过,我认为这个答案可以帮助一些人find类似的症状。 我应该如何注意这一点?