使用PageTransformer在嵌套片段中使用ViewPager的dispatchDraw上的Nullpointerexception

我正在研究的Android应用程序中有一个非常不明显的bug。 我有一个片段,它依次包含一个由FragmentStatePagerAdapter支持的ViewPager。 寻呼机包含两个片段。

每当我尝试添加一个PageTransformer(使用Android开发者网站上的那些: http : //developer.android.com/training/animation/screen-slide.html ),一切正常,直到我试图离开片段包含viewpager(backpress或regular)。 我得到的错误如下。 我无法真正追踪导致它的原因x_x。 底部的寻呼机结构的代码片段。

Process: edu.utcs.android, PID: 11728 java.lang.NullPointerException at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2946) at android.view.View.draw(View.java:14476) at android.support.v4.view.ViewPager.draw(ViewPager.java:2171) at android.view.View.getDisplayList(View.java:13370) at android.view.View.getDisplayList(View.java:13412) at android.view.View.draw(View.java:14190) at android.view.ViewGroup.drawChild(ViewGroup.java:3103) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2940) at android.view.View.draw(View.java:14476) at android.widget.FrameLayout.draw(FrameLayout.java:472) at android.view.View.getDisplayList(View.java:13370) at android.view.View.getDisplayList(View.java:13412) at android.view.View.draw(View.java:14190) at android.view.ViewGroup.drawChild(ViewGroup.java:3103) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2940) at android.view.View.getDisplayList(View.java:13365) at android.view.View.getDisplayList(View.java:13412) at android.view.View.draw(View.java:14190) at android.view.ViewGroup.drawChild(ViewGroup.java:3103) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2959) at android.view.View.getDisplayList(View.java:13365) at android.view.View.getDisplayList(View.java:13412) at android.view.View.draw(View.java:14190) at android.view.ViewGroup.drawChild(ViewGroup.java:3103) at android.support.v4.widget.DrawerLayout.drawChild(DrawerLayout.java:870) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2940) at android.view.View.getDisplayList(View.java:13365) at android.view.View.getDisplayList(View.java:13412) at android.view.View.draw(View.java:14190) at android.view.ViewGroup.drawChild(ViewGroup.java:3103) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2940) at android.view.View.getDisplayList(View.java:13365) at android.view.View.getDisplayList(View.java:13412) at android.view.View.draw(View.java:14190) at android.view.ViewGroup.drawChild(ViewGroup.java:3103) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2940) at android.view.View.draw(View.java:14476) at com.android.internal.widget.ActionBarOverlayLayout.draw(ActionBarOverlayLayout.java:381) at android.view.View.getDisplayList(View.java:13370) at android.view.View.getDisplayList(View.java:13412) at android.view.View.draw(View.java:14190) at android.view.ViewGroup.drawChild(ViewGroup.java:3103) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2940) at android.view.View.draw(View.java:14476) at android.widget.FrameLayout.draw(FrameLayout.java:472) at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2324) at android.view.View.getDisplayList(View.java:13370) at android.view.View.getDisplayList(View.java:13412) at android.view.HardwareRenderer$GlRenderer.buildDisplayList(HardwareRenderer.java:1577) at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1449) at android.view.ViewRootImpl.draw(ViewRootImpl.java:2410) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2282) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1912) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1022) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5708) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) at android.view.Choreographer.doCallbacks(Choreographer.java:562) at android.view.Choreographer.doFrame(Choreographer.java:532) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5083) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593) at de.robv.andro 

寻呼机结构:

 mAdapter = new LabPagerAdapter(getChildFragmentManager()); mPager.setAdapter(mAdapter); mPager.setPageTransformer(false, new ZoomOutPageTransformer()); mPager.setCurrentItem(mLabPosition); 

我已经尝试重新排列一些行,以防它出现某种竞争条件,并尝试反转动画(第3行的“假”布尔值),但没有运气。

编辑

通过一些试验和错误,以及来自user2152081的一些帮助,我通过使用我自己的方法覆盖ViewPager类,并在try / catch块中的draw()中包装超级调用,进行了一个hacky解决方法。

 @Override public void draw(Canvas canvas) { try { super.draw(canvas); } catch (NullPointerException e) { Log.d("ViewPager", "Nullpointer skipped"); } } 

我没有足够的代表发表评论,所以我会在这里回答。

我遇到了完全相同的问题。 查看ViewGroup的源代码,它正在运行android.support.v4.view.ViewPager的子项并在那里点击NPE。 如你所说,删除页面转换器工作,就像删除PagerTabStrip一样。 我现在正在看它,但它看起来像页面转换器和PagerTabStrip之间的某种不兼容性。

具体来说,当要求ViewPager重绘自身时,在堆栈跟踪的顶部:

 at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2946) at android.view.View.draw(View.java:14476) at android.support.v4.view.ViewPager.draw(ViewPager.java:2171) 

对我来说,此时ViewPager只有一个孩子 – PagerTabStrip。 在ViewGroup中的dispatchDraw中,这是NPE弹出的位置:

 for (int i = 0; i < count; i++) { final View child = children[getChildDrawingOrder(count, i)]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { more |= drawChild(canvas, child, drawingTime); } } 

其中children []包含PagerTabStrip作为第0个条目,由于某种原因,子[getChildDrawingOrder(count,i)]正在评估为null。

 getchildDrawingOrder(count, i) 

在我的实现中没有重载,所以它只返回i。 它超出了我为什么评估为null - 它看起来肯定应该返回PagerTabStrip,但它不是,并且它在尝试访问子[0]的成员时产生NPE。

我没有你的解决方案,但希望这与你遇到的情况类似。 如果你发现任何事情,请告诉我。

编辑

不太清楚为什么,但用这个替换我的ViewPager似乎解决了崩溃:

 package ca.test; import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; public class TestViewPager extends ViewPager { public TestViewPager(Context context) { super(context); } public TestViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected int getChildDrawingOrder(int childCount, int i) { return i; } }