试图从视图中删除片段在 mNextAnim 上给了我 NullPointerException
Posted
技术标签:
【中文标题】试图从视图中删除片段在 mNextAnim 上给了我 NullPointerException【英文标题】:Trying to remove fragment from view gives me NullPointerException on mNextAnim 【发布时间】:2014-04-24 17:51:33 【问题描述】:我有 3 个片段,一个 NavigationDrawer、一个 MapFragment 和一个用户定义的“MapInfoFragment”。我希望“MapInfoFragment”在某些事件上在 MapFragment 顶部显示为半透明,而在其他事件上消失。我真的不在乎我是否完全删除片段并每次创建一个新片段,或者我只是更改显示的可见性和信息。目前我只是尝试使用 FragmentManager 的 .hide() 函数,但我也尝试过 .remove 和 .detach ,结果相似。
错误:
03-18 14:28:10.965 24711-24711/com.[packageName].asTest D/androidRuntime﹕ Shutting down VM
03-18 14:28:10.965 24711-24711/com.[packageName].asTest E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.[packageName].asTest, PID: 24711
java.lang.NullPointerException: Attempt to write to field 'int android.app.Fragment.mNextAnim' on a null object reference
at android.app.BackStackRecord.run(BackStackRecord.java:658)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1447)
at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
Activity_main.xml:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_
android:layout_
tools:context="com.[packageName].asTest.MainActivity">
<!-- As the main content view, the view below consumes the entire
space available using match_parent in both dimensions. -->
<FrameLayout
android:id="@+id/container"
android:layout_
android:layout_ >
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_
android:layout_
map:cameraZoom="8"
map:mapType="satellite"
map:uiRotateGestures="false"
android:layout_gravity="center_horizontal|top"
/>
</FrameLayout>
<fragment android:id="@+id/navigation_drawer"
android:layout_
android:layout_
android:layout_gravity="start"
android:name="com.[packageName].asTest.NavigationDrawerFragment"
tools:layout="@layout/simple_list_item_1" />
<fragment android:id="@+id/map_info"
android:layout_
android:layout_
android:name="com.[packageName].asTest.MapInfoFragment" />
</android.support.v4.widget.DrawerLayout>
违规代码:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.hide(getFragmentManager().findFragmentById(R.id.map_info));
ft.commit();
更新 1
我将map_info_layout
更改为map_info
,我得到的错误没有变化。我之前将 map_info_layout
定义为 MapInfoFragment 布局 xml 的根 FrameLayout 的 id,所以我认为 map_info_layout
和 map_info
指向同一个东西。
更新 2:我的解决方案
原来我有MapInfoFragment
扩展android.support.v4.app.Fragment
而不是android.app.Fragment
,我使用的是android.app.FragmentTransaction
而不是android.support.v4.app.FragmentTransaction
。将所有内容切换到android.app.
,因为我对旧设备的兼容性不感兴趣。谢谢弗洛。
更新 3:通用解决方案
停止尝试隐藏空对象
【问题讨论】:
可能我错了,但我没有看到名为map_info_layout
的片段,在您的布局中,我只看到map_info
。
【参考方案1】:
我知道你自己解决了这个问题,但我想解释一下这个错误是如何发生的,因为它只是发生在我身上。
基本上你是在调用hide()
、remove()
等,并带有一个空值。
错误并不明显,发生这种情况时堆栈跟踪并非源自您自己的来源,因此了解它是什么并非易事。
【讨论】:
+ 1 指出这一点。Attempt to write to field 'int *.mNextAnim' on a null object reference
在尝试 show() 或 hide() 传递空片段时引发。 F.
这应该是正确的答案,在这个问题上浪费了很多时间,直到我发现:“基本上你正在调用 hide()、remove() 等,但值为空。”谢谢
我不得不使用getFragmentManager().findFragmentById(R.id.faultyFragment)
而不是getFragmentManager().findFragmentById(mReferenceToFaultyFragment.getId())
。我在onCreateView()
得到了参考【参考方案2】:
当您调用FragmentManager.popBackstack()
时,后台堆栈中没有片段时也会发生这种情况。
【讨论】:
你是怎么解决的?我试过 getBackStackEntryCount() 并没有用。 如果 backstack 中没有片段,我通过不执行 popbackstack 来修复它。 你到底是如何检查 backstack 中的 Fragment 的?我已经尝试过 fragmentManager.findFragmentById(CONTAINER_ID) != null 并且它也不起作用。不知道还要检查什么。 我不检查后台堆栈。我刚刚编写了我的代码,这样如果后台堆栈中没有片段,它就不会弹出后台堆栈。如果你不知道里面有什么,我认为一般来说弹出 backstack 是个坏主意。 改用popBackStackImmediate()
【参考方案3】:
这是因为你现在添加或显示或隐藏了一个为空的片段,在你使用它之前尝试检查它是否为空!
【讨论】:
在我可以替换任何片段之前发生在我身上。它发生在FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
【参考方案4】:
我的问题是 FragmentManager 的 getFragments() 有时会返回一个列表,其中一些片段为空,而我正在删除那些空片段。
【讨论】:
似乎是我的情况,但我从 ChildFragmentManager 中获取了片段。谢谢!【参考方案5】:只有当我从导航抽屉中的一个片段中使用
显示一个 DialogFragment 时,它才发生在我身上newFragment.show(getFragmentManager(), "dialog");
如果我使用了
newFragment.show(getChildFragmentManager(), "dialog");
这没有发生。
注意:当显示或关闭对话框时,崩溃并没有发生在我身上,而是在从导航抽屉更改为另一个片段时发生。
【讨论】:
【参考方案6】:正确调用 show() 和 hide()...
private void showFragment(int fragmentIndex, boolean addToBackStack)
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
for (int i = 0; i < fragments.length; i++)
if (i == fragmentIndex)
transaction.show(fragments[i]);
else
transaction.hide(fragments[i]);
if (addToBackStack)
transaction.addToBackStack(null);
transaction.commit();
【讨论】:
【参考方案7】:如果需要使用getSupportFragmentManager(),除了做空检查外,还必须检查当前是否添加了该片段。如果只使用空值,它仍然会崩溃。这将起作用:
if (fragment != null && fragment.isAdded())
getSupportFragmentManager().beginTransaction().
remove(getSupportFragmentManager().findFragmentById(R.id.fragment_container)).commit();
【讨论】:
以上是关于试图从视图中删除片段在 mNextAnim 上给了我 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章
Android Fragment null 对象 mNextAnim 内部崩溃
ServiceStack:升级到 5.4.1 在 ServiceStack.Common 上给了我 ReflectionTypeLoadException