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 theFragmentManager
. This may include those that are hidden as well as those that are shown. This will not include anyfragments
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.