13

While using the hierarchy viewer in order to reduce hierarchies, I've noticed that on each addition of a fragment (both in "static" or "dynamic" way) the fragments is always wrapped in a new FrameLayout.

Here's an example:

This is my activity layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="mainActivityRoot" >

<TextView
    android:id="@+id/hello_world"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

<fragment
    android:name="com.example.testfragments.MainFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/hello_world" />

</RelativeLayout>

And this is the fragment layout:

<ProgressBar android:id="@+id/ProgressBar1" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:contentDescription="mainFragmentRoot"
android:layout_height="match_parent" />

The activity source code is empty besides the setContentView, And the fragment source code contains only

@Override
public View onCreateView(...) {
    return inflater.inflate(R.layout.fragment_main, container, false);
}

Now,

I would expect to see the PrograssBar directly in the hierarchy of the activity root, but instead there's an additional FrameLayout that I have no idea where it comes from. Here's a screen shot, painted the extra frame in YELLOW: Dump view hierarchy - yellow is bad

So, my questions is - where did it come from? and can I get rid of it? In my real application those extra FrameLayouts are creating very deep hierarchies which are probably bad for performance.

Thanks!

Sean
  • 5,176
  • 2
  • 34
  • 50

1 Answers1

12

It seems like you are using the support v4 library and you forgot to put and id to your fragment xml tag :), so:

where did it come from?

It comes from line 888 of FragmentManager where you can see this:

f.mView = NoSaveStateFrameLayout.wrap(f.mView);

The reason for this is backwards compatibility and it is better explained in the comment header of NoSaveStateFrameLayout which says:

/**
 * Pre-Honeycomb versions of the platform don't have {@link View#setSaveFromParentEnabled(boolean)},
 * so instead we insert this between the view and its parent.
 */

can I get rid of it?

Well, I can think of three options:

  1. You could have your very own implementation of FragmentManager say based on support v4 library version in which you omit this container, but I think the effort of writing/maintaining that code is not worth, plus I don't think the overhead due those FrameLayouts is gigantic, if you are having performance issues you probably have other View optimizations to perform besides this (say write a custom view -which extends View-) or say rethink your layout/fragments to reduce the amount of views in the hierarchy at certain point.
  2. Wait for a new release of support v4 library which accomplishes 1. <- yup I'm a lazy person :D, you'll have to file a bug if there is not one already (see 3.), the cool part of this is you could even contribute your patch or someone else as well.
  3. Support only platforms (or wait until) where the support v4 library is not (longer) needed, in API level 11+ FragmentManager implementation does not have this nested ViewGroup (see line 861 of 11+ FragmentManager), on those you get something like this:

Look mom!, no nested <code>FrameLayout</code>!!1

I wouldn't worry much for those as I mentioned there are other optimizations you can invest that time in ;)

eveliotc
  • 12,863
  • 4
  • 38
  • 34
  • You sir - Rock! thank you very much for the comprehensive answer. – Sean May 28 '13 at 07:53
  • 2
    I have opened an issue for that: https://code.google.com/p/android/issues/detail?id=68057&thanks=68057&ts=1396459349 – Sean Apr 02 '14 at 17:24
  • Is there a way to get the FrameLayout added by the Fragment? I'd like to set its `clipChildren` to false because it's clipping its children views. – Richard May 07 '20 at 03:56