Android ViewPaper使用FragmentPagerAdapter出现的FragmentManagerImpl为空的问题

问题描述

在使用ViewPaper结合FragmentPagerAdapter实现fragment滑动切换过程中,插入OTG存储设备,进入界面很卡顿,弹出停止运行提示。

问题类型
INT,ANR

堆栈信息

10-22 17:43:10.683  3175  3175 E AndroidRuntime: FATAL EXCEPTION: main
10-22 17:43:10.683  3175  3175 E AndroidRuntime: Process: com.xxx.xxxx, PID: 3175
10-22 17:43:10.683  3175  3175 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.FragmentManagerImpl.performPendingDeferredStart(android.support.v4.app.Fragment)' on a null object reference
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.support.v4.app.Fragment.setUserVisibleHint(Fragment.java:879)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem(FragmentPagerAdapter.java:130)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.support.v4.view.ViewPager.populate(ViewPager.java:1104)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:552)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:514)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:506)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at com.xxx.xxxx.ui.MyActivity.setTabSelection(MyActivity.java:477)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at com.xxx.xxxx.ui.MyActivity.access$2100(MyActivity.java:69)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at com.xxx.xxxx.ui.MyActivity$MyTabOnClickListener.onClick(MyActivity.java:301)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.view.View.performClick(View.java:5212)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.view.View$PerformClick.run(View.java:21214)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.os.Handler.handleCallback(Handler.java:739)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:95)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:148)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:5619)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:850)
10-22 17:43:10.683  3175  3175 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:734)

原因分析

从堆栈信息分析,只因为FragmentPagerAdapter中的fragmentManager为空导致的,但是排查代码,发现fragmentmanager是来自fragmentActivity的getSupportFragmentManager,而且在onCreate中已经初始化了的,并且在整个Activity中并没有出现置空的语句。那问题就来了,为什么fragment为空呢?
1、多线程问题,在其他地方修改了fragmentManager
根据前面的分析,排查后发现不可能为该问题引起。
2、viewpaper的切换出现在了错误的时机,fragmentmanager已被回收
根据现象的描述,出现问题前界面卡顿,那会不会是响应界面切换的时候,进入了一个错误的时机。确实,这种可能性是很大的,但是所谓的错误的时机又是什么呢?这个时机应该就是,viewpaper的切换响应在了fragmentmanager被回收之后,然而根据Activity的生命周期,资源的回收应该是在onDestroy之中。所以大胆猜想,在viewpaper切换界面的时候,由于系统原因(anr),导致切换时间延后了,当事件被响应的时候已经是Activity销毁之后了。

问题复现

根据原因分析中的第2点,尝试复现问题。首先,在onDestroy中添加代码行mViewPager.setCurrentItem(index, false);运行apk。进入Activity,然后退出Activity。发现应用停止运行,抓取log,发现log一样。

解决办法

该问题属于小概率的问题,一般情况下,viewpaper的界面切换都可以立即响应的。针对该问题,考虑到viewpaper切换界面的过程是无法中断的,所以无法再onDestroy中添加中断操作,阻止错误时机下的切换操作。所以只能对这一现象添加防呆操作,合理性在于,界面的切换出现在onDestroy之后是没有意义的。那在哪里防呆比较合适呢,这就要看我们的代码能够得到那里了。回看log信息,从上往下看,实现过程自定义了一个adapter继承自FragmentPagerAdapter,巧的是,android.support.v4.app.FragmentPagerAdapter.setPrimaryItem(FragmentPagerAdapter.java:130),该方法使我们能够到的最底的地方,所以在这里防呆比较合适。防呆方法就是重写该方法,捕获父类该方法的实现。具体如下:

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        // TODO 自动生成的方法存根
        try {
            super.setPrimaryItem(container, position, object);
        } catch (Exception e) {
            // TODO: handle exception
            LogUtils.e("MyFragAdapter", "", e);
        }
    }

相关链接

http://stackoverflow.com/questions/10456077/nullpointerexception-in-fragmentmanager

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值