diff --git a/docs/html/topic/performance/images/lint-display.png b/docs/html/topic/performance/images/lint-display.png new file mode 100644 index 0000000000000..e3609381a4c45 Binary files /dev/null and b/docs/html/topic/performance/images/lint-display.png differ diff --git a/docs/html/topic/performance/images/lint-inspect-code.png b/docs/html/topic/performance/images/lint-inspect-code.png new file mode 100644 index 0000000000000..41604a1825213 Binary files /dev/null and b/docs/html/topic/performance/images/lint-inspect-code.png differ diff --git a/docs/html/topic/performance/optimizing-view-hierarchies.jd b/docs/html/topic/performance/optimizing-view-hierarchies.jd new file mode 100644 index 0000000000000..644cc5a9ddaec --- /dev/null +++ b/docs/html/topic/performance/optimizing-view-hierarchies.jd @@ -0,0 +1,388 @@ +page.title=Performance and the View Hierarchy +@jd:body + +
+
+ +

In this document

+
    +
  1. Layout-and-Measure Performance +
      +
    1. Managing complexity: layouts matter
    2. +
    3. Double taxation
    4. +
    +
  2. +
  3. Diagnosing View Hierarchy Issues +
      +
    1. Systrace
    2. +
    3. Profile GPU rendering
    4. +
    5. Lint
    6. +
    7. Hierarchy Viewer
    8. +
    +
  4. +
  5. Solving View Hierarchy Issues +
      +
    1. Removing redundant nested layouts
    2. +
    3. Adopting a cheaper layout
    4. +
    +
  6. +
+
+
+ + +

+The way you manage the hierarchy of your {@link android.view.View} objects can +have a substantial impact on your app’s performance. This page describes how to +assess whether your view hierarchy is slowing your app down, and offers some +strategies for addressing issues that may arise. +

+ +

Layout and Measure Performance

+

+The rendering pipeline includes a layout-and-measure +stage, during which the system appropriately positions the relevant items in +your view hierarchy. The measure part of this stage determines the sizes and +boundaries of {@link android.view.View} objects. The layout part determines where on the screen to +position the {@link android.view.View} objects. +

+ +

+Both of these pipeline stages incur some small cost per view or layout that they +process. Most of the time, this cost is minimal and doesn’t noticeably affect +performance. However, it can be greater when an app adds or removes View +objects, such as when a {@link android.support.v7.widget.RecyclerView} +object recycles them or reuses them. The +cost can also be higher if a {@link android.view.View} object needs to consider +resizing to main its constraints: For example, if your app calls +{@link android.widget.TextView#setText(char[], int, int) SetText()} on a +{@link android.view.View} object that wraps text, the +{@link android.view.View} may need to resize. +

+ +

+If cases like these take too long, they can prevent a frame from rendering +within the allowed 16ms, so that frames are dropped, and animation becomes +janky. +

+ +

+Because you cannot move these operations to a worker thread—your app must +process them on the main thread—your best bet is to optimize them so that +they can take as little time as possible. +

+ +

Managing complexity: layouts matter

+ +

+Android Layouts +allow you to nest UI objects in the view hierarchy. This nesting can also impose +a layout cost. When your app processes an object for layout, the app performs +the same process on all children of the layout as well. For a complicated +layout, sometimes a cost only arises the first time the system computes the +layout. For instance, when your app recycles a complex list item in a +{@link android.support.v7.widget.RecyclerView} object, the +system needs to lay out all of the objects. In another example, trivial changes +can propagate up the chain toward the parent +until they reach an object that doesn’t affect the size of the parent. +

+ +

+The most common case in which layout takes an especially long time is when +hierarchies of {@link android.view.View} objects are nested within one another. Each nested layout +object adds cost to the layout stage. The flatter your hierarchy, the less +time that it takes for the layout stage to complete. +

+ +

+If you are using the {@link android.widget.RelativeLayout} class, you may be able to achieve the same +effect, at lower cost, by using nested, unweighted +{@link android.widget.LinearLayout} views instead. Additionally, if your app +targets Android N (API level 24), it is likely that +you can use a special layout editor to create a {@code ConstraintLayout} +object instead of {@link android.widget.RelativeLayout}. Doing so allows you +to avoid many of the issues this section +describes. The {@code ConstraintLayout} +class offers similar layout control, but +with much-improved performance. This class uses its own constraint-solving +system to resolve relationships between views in a very different way from +standard layouts. +

+ +

Double Taxation

+ +

+Typically, the framework executes the layout +or measure stage in a single pass and quite quickly. However, with some more +complicated layout cases, the framework may have to iterate multiple times on +the layout or measure stage before ultimately positioning the elements. Having +to perform more than one layout-and-measure iteration is referred to as +double taxation. +

+ +

+For example, when you use the {@link android.widget.RelativeLayout} container, which allows you to +position {@link android.view.View} objects with respect to the positions of other {@link android.view.View} objects, the +framework performs the following actions: +

+ +
    +
  1. Executes a layout-and-measure pass, during which the framework calculates +each child object’s position and size, based on each child’s request. +
  2. Uses this data, also taking object weights into account, to figure out the +proper position of correlated views. +
  3. Performs a second layout pass to finalize the objects’ positions. +
  4. Goes on to the next stage of the rendering process.
+ +

+The more levels your view hierarchy has, the greater the potential performance +penalty. +

+ +

+Containers other than {@link android.widget.RelativeLayout} may also give rise to double taxation. For +example: +

+ + +

+Multiple layout-and-measure passes are not, in themselves, a performance burden. +But they can become so if they’re in the wrong spot. You should be wary of +situations where one of the following conditions applies to your container: +

+ + + +

Diagnosing View Hierarchy Issues

+ +

+Layout performance is a complex problem with many facets. There are a couple of +tools that can give you solid indications about where performance bottlenecks +are occurring. A few other tools provide less definitive information, but can +also provide helpful hints. +

+ +

+

Systrace

+

+ +

+One tool that provides excellent data about performance is Systrace, +which is built into Android Studio. The Systrace tool allows you to collect and +inspect timing information across an entire Android device, allowing you to see +specifically where performance bottlenecks arise. For more information about +Systrace, see +Analyze UI Performance with Systrace. +

+ +

Profile GPU rendering

+ +

+The other tool most likely to provide you with concrete information about +performance bottlenecks is the on-device +Profile GPU rendering tool, available on devices powered by Android 6.0 (API +level 23) and later. This tool allows you to see how long the layout-and-measurestage is + taking for each frame +of rendering. This data can help you diagnose runtime performance issues, +and help you determine what, if any layout-and-measure issues you need to +address. +

+ +

+In its graphical representation of the data it captures, Profile +GPU rendering uses the color blue to represent layout time. For more +information about how to use this tool, see Profile +GPU Rendering Walkthrough. +

+ +

Lint

+ +

+AndroidStudio’s Lint tool can +help you gain a sense of inefficiencies in the view hierarchy. To use this tool, +select Analyze > Inspect Code, as shown in Figure 1. +

+ + +

+ Figure 1. Locating Inspect Code in the +Android Studio. +

+ +

+Information about various layout items appears under +Android > Lint > Performance. To see more detail, +you can click on each item to expand it, and see more +information in the pane on the right side of the screen. +Figure 2 shows an example of such a display. +

+ + +

+ Figure 2. Viewing information about specific +issues that the lint tool has identified. +

+ + +

+Clicking on one of these items reveals, in the pane to the right, the problem +associated with that item. +

+ +

+To understand more about specific topics and issues in this area, see the Lint +documentation. +

+ +

Hierarchy Viewer

+ +

+Android Studio’s Hierarchy +Viewer tool provides a visual representation of your app’s view hierarchy. +It is a good way to navigate the hierarchy of your app, providing a clear visual +representation of a particular view’s parent chain, and allowing you to inspect +the layouts that your app constructs. +

+ +

+The views that Hierarchy Viewer presents can also help identify performance +problems arising from double taxation. It can also provide an easy way for you +to identify deep chains of nested layouts, or layout areas with a large amount +of nested children, another potential source of performance costs. In these +scenarios, the layout-and-measure stages can be particularly costly, +resulting in performance issues. +

+ +

+You can also can get a sense of relative time taken by layout-and-measure +operations by clicking the “profile node” button. +

+ +

+For more information about Hierarchy Viewer, see Optimizing +Your UI. +

+ +

Solving View Hierarchy Issues

+ +

+The fundamental concept behind solving performance problems that arise from view +hierarchies is simple in concept, but more difficult in practice. Preventing +view hierarchies from imposing performance penalties encompasses the dual goals +of flattening your view hierarchy and reducing double taxation. This section +discusses some strategies for pursuing these goals. +

+ +

Removing redundant nested layouts

+ +

+Developers often use more nested layouts than necessary. For example, a +{@link android.widget.RelativeLayout} container might contain a single child that is also a +{@link android.widget.RelativeLayout} container. This nesting amounts to redundancy, and adds +unnecessary cost to the view hierarchy. +

+ +

+Lint can often flag this problem for you, reducing debugging time. +

+ +

Adopting Merge/Include

+

+One frequent cause of redundant nested layouts is the +<include> +tag. For example, you may define a re-usable layout as follows: +

+ +
+<LinearLayout>
+    <!-- some stuff here -->
+</LinearLayout>
+</pre>
+
+ +

+And then an include tag to add this item to the parent container: +

+ +
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/app_bg"
+    android:gravity="center_horizontal">
+
+    <include layout="@layout/titlebar"/>
+
+    <TextView android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:text="@string/hello"
+              android:padding="10dp" />
+
+    ...
+
+</LinearLayout>
+
+ +

+The include unnecessarily nests the first layout within the second layout. +

+ +

+The merge +tag can help prevent this issue. For information about this tag, see Re-using +Layouts with <include>. +

+ +

Adopting a cheaper layout

+ +

+You may not be able to adjust your existing layout scheme so that it doesn’t +contain redundant layouts. In certain cases, the only solution may be to flatten +your hierarchy by switching over to an entirely different layout type. +

+ +

+For example, you may find that a {@link android.widget.TableLayout} +provides the same functionality as a more complex layout with many +positional dependencies. In the N release of Android, the +{@code ConstraintLayout} class provides similar functionality to +{@link android.widget.RelativeLayout}, but at a significantly lower cost. +