试图从视图中删除片段在 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_layoutmap_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

从其他片段启动视频视图片段时显示问题?

在tablayout中替换片段