0

I faced a problem debugging a code and the problem is that based on this:

public List getFragments ()

Get a list of all fragments that are currently added to the FragmentManager. This may include those that are hidden as well as those that are shown. This will not include any fragments only in the back stack, or fragments that are detached or removed.

when a fragment is detached it shouldn't be included in the returned list but by running this code:

public class MainActivity extends AppCompatActivity {

    FragmentManager mFragmentManager = getSupportFragmentManager();
    FragmentTransaction mFragmentTransaction = mFragmentManager.beginTransaction();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mFragmentManager.registerFragmentLifecycleCallbacks(new FragmentManager.FragmentLifecycleCallbacks() {
            @Override
            public void onFragmentDetached(@NonNull FragmentManager fm, @NonNull Fragment f) {
                super.onFragmentDetached(fm, f);
                Log.e("DetachDetected", f.getTag() + " Detached");
            }
        },false);

        super.onCreate(savedInstanceState);


        List<Fragment> lf = getSupportFragmentManager().getFragments();
        Log.e("ActivityOnCreate" , "Content hasn't been set yet");
        Log.e("ListInfo" , "Fragment list size is:" + lf.size());

        setContentView(R.layout.activity_main);

        Log.e("ActivityOnCreate" , "Content has been set");
        lf = getSupportFragmentManager().getFragments();
        Log.e("ListInfo" , "Fragment list size is:" + lf.size());

        MyFragment myFragment = new MyFragment();
        mFragmentTransaction.replace(R.id.f_container, myFragment);
        mFragmentTransaction.commit();
    }

    @Override
    protected void onStart() {
        Log.e("ActivityInfo" , "Initiating MainActivity.onStart");
        super.onStart();
        List<Fragment> lf = getSupportFragmentManager().getFragments();
        Log.e("ListInfo" , "Fragment list size is:" + lf.size());
    }

    @Override
    protected void onDestroy() {
        Log.e("ActivityInfo" , "Initiating MainActivity.onDestroy");
        super.onDestroy();
    }
}

and changing the orientation, in the log I get:

2020-04-19 04:02:17.693 17382-17382/? E/ActivityOnCreate: Content hasn't been set yet
2020-04-19 04:02:17.693 17382-17382/? E/ListInfo: Fragment list size is:0
2020-04-19 04:02:17.750 17382-17382/? E/ActivityOnCreate: Content has been set
2020-04-19 04:02:17.750 17382-17382/? E/ListInfo: Fragment list size is:1
2020-04-19 04:02:17.751 17382-17382/? E/ActivityInfo: Initiating MainActivity.onStart
2020-04-19 04:02:17.753 17382-17382/? E/DetachDetected: my_fragment Detached
2020-04-19 04:02:17.756 17382-17382/? E/ListInfo: Fragment list size is:1
2020-04-19 04:02:43.349 17382-17382/com.example.fragmentlife E/ActivityInfo: Initiating MainActivity.onDestroy
2020-04-19 04:02:43.350 17382-17382/com.example.fragmentlife E/DetachDetected: null Detached
2020-04-19 04:02:43.363 17382-17382/com.example.fragmentlife E/ActivityOnCreate: Content hasn't been set yet
2020-04-19 04:02:43.363 17382-17382/com.example.fragmentlife E/ListInfo: Fragment list size is:1
2020-04-19 04:02:43.370 17382-17382/com.example.fragmentlife E/AndroidRuntime: FATAL EXCEPTION: main

which begs the question why the fragment is still there and I think this actually causes this error (the actual reason I'm here):

 Caused by: android.view.InflateException: Binary XML file line #18: Binary XML file line #18: Error inflating class fragment
 Caused by: android.view.InflateException: Binary XML file line #18: Error inflating class fragment
 Caused by: java.lang.IllegalStateException: Fragment com.example.fragmentlife.MyFragment did not create a view.
    at androidx.fragment.app.FragmentManagerImpl.onCreateView(FragmentManagerImpl.java:3234)
 ...

a few lines before FragmentManagerImpl.java:3234, "movetostate" function checks if there was a state of this fragment and if there was it tries to get its view and inflate it but after detaching (I believe the view is destroyed at this point) it doesn't find a view and causes the error by doing:

throw new IllegalStateException("Fragment " + fname + " did not create a view.");

Am I getting that Doc wrong?

MyFragment class:

public class MyFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fgment, container, false);
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/f_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginBottom="50dp">

        <fragment
            android:id="@+id/fragment"
            android:name="com.example.fragmentlife.MyFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:tag="my_fragment"/>

    </RelativeLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

and lastly fgment.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#1C39BB">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textColor="#DEDEDE"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Note: If i override activity's onPause() like this:

    @Override
    protected void onPause() {
        List<Fragment> lf = mFragmentManager.getFragments();
        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
        for(Fragment f : lf) {
            fragmentTransaction.remove(f);
        }
        fragmentTransaction.commit();
        super.onPause();
    }

I don't get that inflater error. Thought this might help.

Alak
  • 1
  • 2
  • You should not access `FragmentManager` after activitiy `super.onDestroy` since at that point fragment manager is destroyed as well. – Pawel Apr 18 '20 at 21:32
  • yep. Thanks @Pawel. Edited the code for further clarification of the problem. – Alak Apr 19 '20 at 11:23

0 Answers0