46

I've got 3 fragments, one NavigationDrawer, one MapFragment, and one user-defined "MapInfoFragment". I want the "MapInfoFragment" to appear semi-transparent over top of the MapFragment on certain events and disappear on others. I don't really care if I completely remove the fragment and create a new one each time, or I just change the visibility and information displayed. Currently I'm just trying to use FragmentManager's .hide() function, but I've also tried .remove and .detach with similar results.

Error:

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_width="match_parent"
    android:layout_height="match_parent"
    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_width="match_parent"
        android:layout_height="match_parent" >

        <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_width="match_parent"
            android:layout_height="match_parent"
            map:cameraZoom="8"
            map:mapType="satellite"
            map:uiRotateGestures="false"
            android:layout_gravity="center_horizontal|top"
        />
    </FrameLayout>

    <fragment android:id="@+id/navigation_drawer"
        android:layout_width="@dimen/navigation_drawer_width"
        android:layout_height="match_parent"
        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_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.[packageName].asTest.MapInfoFragment" />




</android.support.v4.widget.DrawerLayout>

Offending Code:

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.hide(getFragmentManager().findFragmentById(R.id.map_info));
ft.commit();

Update 1

I changed map_info_layout to map_info and there's no change in the error I'm getting. I'd previously had map_info_layout defined as the id for the root FrameLayout of the MapInfoFragment's layout xml, so I think map_info_layout and map_info were pointing to the same thing.

Update 2: My solution

Turned out that I had MapInfoFragment extending android.support.v4.app.Fragment instead of android.app.Fragment and I was using the android.app.FragmentTransaction instead of android.support.v4.app.FragmentTransaction. Switched everything to android.app. since I'm not interested in older device compatibility. Thanks Fllo.

Update 3: General solution

Stop trying to hide null objects

Koeber
  • 571
  • 1
  • 4
  • 6
  • 1
    Might be I'm wrong, but I don't see a fragment named `map_info_layout`, in your layout, I only see `map_info`. – Blo Mar 18 '14 at 20:04

7 Answers7

116

I know you've solved this yourself, but I want to explain how this error happens, since it just happened to me.

Basically you're calling hide(), remove(), etc., with a null value.

The error isn't obvious, and the stack trace doesn't originate from your own sources when this happens, so it's not trivial to realise what it is.

gak
  • 32,061
  • 28
  • 119
  • 154
  • 14
    + 1 for pointing this out. `Attempt to write to field 'int *.mNextAnim' on a null object reference` is raised when trying to show() or hide() passing a null fragment. F. – Flashbump Jan 23 '15 at 22:13
  • This should be the correct answer, lost so much time with this issue until I've found that: "Basically you're calling hide(), remove(), etc., with a null value." Thanks – GuilhE Jun 30 '15 at 11:25
  • 2
    I had to use `getFragmentManager().findFragmentById(R.id.faultyFragment)` instead of `getFragmentManager().findFragmentById(mReferenceToFaultyFragment.getId())`. I got the reference in `onCreateView()` – OneWorld Jul 02 '15 at 10:58
8

It also happens when you call FragmentManager.popBackstack() without there being a fragment in the backstack.

Christine
  • 5,617
  • 4
  • 38
  • 61
  • How did you solve it? I tried getBackStackEntryCount() and it did not work. – Ineta Dec 05 '16 at 08:48
  • I fixed it by not doing a popbackstack if there's no fragment in the backstack. – Christine Dec 05 '16 at 09:00
  • How exactly did you check for fragments in the backstack? I've tried fragmentManager.findFragmentById(CONTAINER_ID) != null and it did not work as well. Not sure what else to check. – Ineta Dec 05 '16 at 10:44
  • I don't check in the backstack. I just wrote my code so that it doesn't pop the backstack if there's no fragment in the backstack. I think generally it's a bad idea to pop the backstack if you don't know what's in it. – Christine Dec 05 '16 at 11:03
  • use `popBackStackImmediate()` instead – Desolator Mar 18 '18 at 05:56
4

this is because you add or show or hide a fragment which is null now,try to check if it is null ,before you use it!

howerknea
  • 355
  • 3
  • 12
  • It happens to me before I can replace any fragment. It happens in `FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();` – Mr.Moustard Sep 29 '15 at 12:23
2

My problem was that FragmentManager's getFragments() sometimes returns a list where some fragments are null, and I was removing those null fragments.

flobacca
  • 936
  • 2
  • 17
  • 42
0

It happended to me only when from one of the fragments in the navigation drawer I showed a DialogFragment by using

newFragment.show(getFragmentManager(), "dialog");

If instead I used

newFragment.show(getChildFragmentManager(), "dialog");

this did not happened.

NOTE: The crash did not happen to me when showing or closing the dialog, but when changing to another fragment from the navigation drawer.

0

Properly call show() and 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();
}
0

If you need to use getSupportFragmentManager(), in addition to doing a null check, you must also check to see if that fragment is currently added. If you only use a null, it will still crash. This will work:

if (fragment != null && fragment.isAdded()) {
                    getSupportFragmentManager().beginTransaction().
                            remove(getSupportFragmentManager().findFragmentById(R.id.fragment_container)).commit();
                }
rdmcbath
  • 305
  • 1
  • 9