I wrote this answer because even after going through several StackOverflow pages I wasn't able to clearly grasp what attachToRoot meant. Below is inflate() method in the LayoutInflater class.
View inflate (int resource, ViewGroup root, boolean attachToRoot)
Take a look at activity_main.xml file, button.xml layout and the MainActivity.java file I created.
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
button.xml
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LayoutInflater inflater = getLayoutInflater();
LinearLayout root = (LinearLayout) findViewById(R.id.root);
View view = inflater.inflate(R.layout.button, root, false);
}
When we run the code, we won't see the button in the layout. This is because our button layout is not added into the main activity layout since attachToRoot is set to false.
LinearLayout has an addView(View view) method which can be used to add Views to LinearLayout. This will add the button layout into the main activity layout, and make the button visible when you run the code.
root.addView(view);
Let's remove the previous line, and see what happens when we set attachToRoot as true.
View view = inflater.inflate(R.layout.button, root, true);
Again we see that the button layout is visible. This is because attachToRoot directly attaches the inflated layout to the parent specified. Which in this case is root LinearLayout. Here we don't have to add the views manually like we did in the previous case with addView(View view) method.
Why are people getting IllegalStateException when setting attachToRoot as true for a Fragment.
This is because for a fragment you have already specified where to place your fragment layout in your activity file.
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.root, fragment)
.commit();
The add(int parent, Fragment fragment) adds the fragment which has it's layout to the parent layout. If we set attachToRoot as true, you will get IllegalStateException: The specified child already has a parent. Since fragment layout is already added to the parent layout in the add() method.
You should always pass false for attachToRoot when you're inflating Fragments. It is the FragmentManager’s job to add, remove and replace Fragments.
Back to my example. What if we do both.
View view = inflater.inflate(R.layout.button, root, true);
root.addView(view);
In the first line, LayoutInflater attaches the button layout to the root layout and returns a View object which holds the same button layout. In the second line, we add the same View object to the parent root layout. This results in the same IllegalStateException we saw with Fragments (The specified child already has a parent).
Keep in mind that there is another overloaded inflate() method, which sets attachToRoot as true by default.
View inflate (int resource, ViewGroup root)