Вопрос

I have a FrameLayout that contains a TextView and two LinearLayouts:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >


    ... a textview and 2 linearlayouts


</FrameLayout>

After running Android Lint, I get this warning: This <FrameLayout> can be replaced with a <merge> tag.

Why does this warning exist? What can I do to fix it (other than ignore)?

Это было полезно?

Решение

To understand this, you need to understand how layouts are inflated and placed.

Let's say for example, you have an activity and this is the layout xml you use. Here is what the layout of the activity looks before you put your layout file.

<FrameLayout> // This is the window
    <FrameLayout> // This is activity
    </FrameLayout>
</FrameLayout>

There might be few other layers depending on the device/OS.

Now when you inflate your layout file and put it in, this is how it will look.

<FrameLayout> // This is the window
    <FrameLayout> // This is activity
            //A textview and 2 linearlayouts
    </FrameLayout>
</FrameLayout>

Do you see the FrameLayout inside the other FrameLayout? It is redundant to have that since it does not add much value. To optimize, you can replace your outer FrameLayout with the <merge> tag. This is what it will look like.

<merge> // This is the window
    <FrameLayout> // This is activity
            //A textview and 2 linearlayouts
    </FrameLayout>
</merge>

Notice how there is no extra FrameLayout. Instead, it is just merged with the FrameLayout of the activity. Whenever you can, you should use <merge>. This doesn't only apply to FrameLayouts. You can read more about it here. http://developer.android.com/training/improving-layouts/reusing-layouts.html#Merge

Hope this helps.

Другие советы

Are you using this as the main layout of your activity? If so, you can replace it with a merge tag like this:

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    ... a textview and 2 linearlayouts


</merge>

At setContentView, Android will take the children of the merge tag and directly insert them to the FrameLayout with @android:id/content. Examine both approaches (FrameLayout vs merge) with HierarachyViewer to see the difference.

Refer this post by the Romain Guy for more information. It tells you why the merge option is suggested.

To render the XML in the device a process is followed in phases, and the first one is Measure.

Measure: In this phase, the sizes of the parent and their children and their children, and so on, is measured. So your CPU scans all the ViewGroup and View in your layout to measure their sizes. And sometimes for some reasons, it may require this scanning recursively because of the dependency of the size of the parent and their children on each other.

So why Lint is giving this warning?

Because your XML eventually will be loaded into a window which contains FrameLayout and in your XML file you are also using the FrameLayout, so eventually your XML will be placed in FrameLayout of the window and it will be like this:

<FrameLayout> <!--belongs to window-->
    <FrameLayout> <!--belongs to your XML-->
            ...
    </FrameLayout>
</FrameLayout>

Now there is an overhead for CPU in the measure phase, to measure both the FrameLayout. And this overhead can be overcome if we can somehow manage to use the outer FrameLayout in our XML, that's exactly possible via merge tag.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top