Some optimization points of view rendering in Android application development _android

Source: Internet
Author: User

A common misconception is that the basic layout structure (e.g. linearlayout, framelayout, etc.) can be used in most cases
produce an efficient layout. Obviously, every control and every layout you add to your application needs to be initialized, laid out (layout),
Drawing (Drawing). For example, embedding a linearlayout creates a level of layout that is too deep. More seriously, embedding a few make
LinearLayout with the Layout_weight property will cause a lot of overhead because each child view needs to be measured two times. This is an iterative analysis
Important point when layout files, such as when used in ListView or GridView.

Watch your layout.

The Android SDK Kit includes a tool called "Hierarchy Viewer" that allows you to analyze when your application is running
Layout. By using this tool, you can help you find bottlenecks in the efficiency of your layout.

The Hierarchy Viewer tool allows you to select a running process in a connected device or emulator and then render the layout hierarchy tree
(Layout tree). Traffic lights under each square block (see below)---red-green-blue display in measurement (measure), Layout (layout), and drawing
(draw) The efficiency values in the process, which can help you locate potential problems.

Suppose that an item in ListView exists as follows (see Figure 1) Layout:

The Hierarchy Viewer tool can be found under the <sdk>/tools path. When you open it, the Hierarchy Viewer tool displays the
All available devices and the processes running on those devices. Click "Load View Hierarchy" to display the UI layout of a component you selected
Level. For example, figure 2 shows the layout hierarchy tree for Figure 1.

In Figure 2, you can see visually that there are some problems with this three-layer layout structure. The click items are reflected in each measurement (measure),
Layout (layout), and time consumption during drawing (draw) (see Figure 3). Obviously, the item (LinearLayout) took the longest time to
Measurement, layout, and drawing, you should take some effort to optimize them.

The time to finish rendering the layout file is:
Measuring process: 0.977ms
Layout process: 0.167ms
Drawing process: 2.717ms

Modify a layout file

Because the layout efficiency of the above diagram is low because of an embedded linearlayout control, by flattening the layout file----makes the layout
Lighter and wider, rather than becoming narrower and deeper, so that it improves efficiency. A relativelayout as the root node can also provide the above
Layout effect (that is, figure 1). Therefore, using Relativelayout to change the layout of the design, you can see now our layout level is only 2 layers.
The new layout hierarchy tree is as follows:

Now, the time to finish rendering the layout file is:
Measuring process: 0.977ms
Layout process: 0.167ms
Drawing process: 2.717ms

Maybe it's just a little bit of an improvement, but this time it's going to be called multiple times, because ListView will lay out all the item, accumulate,
The effect of the improvement is still very considerable.

Most of the time difference is due to the use of LinearLayout with the Layout_weight attribute, which slows down the measurement process. This is only
is an example where each layout should be properly used and you should seriously consider whether it is necessary to adopt the "Layout_weight" attribute.

using the Lint tool

A good practice is to use the lint tool in your layout file to look for ways to optimize the layout hierarchy. Lint has replaced layoutopt.
Tool and it provides more powerful functionality. Some lint rules are as follows:

1, using the combination control---contains a imageview and a TextView control linearlayout if it can be used as a
The combined control will be handled more efficiently.
2. Merge the frame layout (framelayout) as the root node----If a frame layout is the root node in the layout file, and it does not have a background picture
Or padding, a more efficient way is to replace the < framelayout/> label with the <merge/> tag.


3, useless leaf node-----Usually if a layout control does not have a child view or a background picture, the layout control can be removed
(because it is in a invisible state).

4, useless parent node-----If a parent view has a child view, but there is no sibling view node, the view is not a ScrollView control or
root node, and it has no background picture and can be removed, and after removal, all child views of the parent view are migrated directly to the previous parent view
Level of layout. can also make parsing layout and layout hierarchy more efficient.

5, too deep layout level----embedded too much layout is always inefficient. Consider using some flat layout controls, such as Relativelayout,
GridLayout, to improve the layout process. The default maximum layout depth is 10.


When developed using the Eclipse environment, lint can automatically solve some of the problems, provide some suggestions, and jump directly to the wrong code to check.
If you don't use Eclipse,lint, you can also run it from the command line.

reusing layout files using <include/> Tags
Although Android provides a small, reusable element of interactivity with a variety of controls built into it, you may need to reuse the larger
Component----Some specific layout files. For more efficient reuse of layout files, you can use <include/> as well as <merge/>
The label adds additional layout files to the current layout file.

Reusing a layout file is a particularly powerful method that allows you to create reusable layout files. For example, one containing "Yse" or "No"
button face version, or ProgressBar with a text description. Reusing a layout file also means that any element in your application can be
Complex layout files are extracted for individual management, and then all you need to do is to add these separate layout files (since they are all reusable).
So, when you create a standalone UI component from a custom view, you can reuse the layout file to make things easier.

1. Create a reusable layout file

If you already know the "face" of the reuse layout, create and define the layout file (named ". xml" as the suffix). For example, here is a
G-kenya Codelab Layout file that defines a custom heading (Titlebar.xml) to be used in each activity: because of these
The reusable layout is added to other layout files, so it is best to be precise (exactly) for each root view.

<framelayout xmlns:android= "http://schemas.android.com/apk/res/android" 
 android:layout_width= "Match_ Parent " 
 android:layout_height=" wrap_content " 
 android:background=" @color/titlebar_bg > 
 
 < ImageView android:layout_width= "wrap_content" 
    android:layout_height= "wrap_content" 
    @ Drawable/gafricalogo "/> 
</FrameLayout> 


2. Use <include/> Label

Where you need to add these layouts, use the <include/> tag. For example, here is a layout file from G-kenya Codelab,
It reused the title bar file listed above, and the layout file is as follows:

<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" 
    @ String/hello " 
    android:padding=" 10DP "/> 
 
 ... 
 
</LinearLayout> 


You can also define a special identifier for the root view of the added layout file in the <include/> node, overriding all layout parameters (any
Attributes that are prefixed with "android:layout_"). For example:

<include android:id= "@+id/news_title" 
   android:layout_width= "Match_parent" 
   Match_parent " 
   layout=" @layout/title "/> 

3. Use <merge/> Label

When you reuse another layout in a layout file, the <merge/> Tag eliminates redundant view elements at the layout level. For example, if your
The primary layout file is a linearlayout that contains two view vertically, which can be reused in other layouts, and for any of the two view
The layout file requires a root View (otherwise, the compiler prompts for an error). However, add a linearlayout to the reusable layout
As Root View, it will cause a vertical linearlayout to contain additional vertical linearlayout. Inline LinearLayout only slows
UI efficiency, the other is useless to say.
The reusable layout utilizes. XML rendering as follows:

<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=" Horizontal "> 
 
 <button 
  android:layout_width=" Fill_parent 
  " android:layout_height= "Wrap_content" 
  android:text= "@string/add"/> <button android:layout_ 
  Width= "Fill_parent" 
  android:layout_height= "wrap_content" 
  android:text= "@string/delete" 
/> </LinearLayout> 


To avoid redundant layout elements, you can use <merge/> As a reusable layout file in root View. For example:
Layout files using the <merge/> Label:

<merge xmlns:android= "Http://schemas.android.com/apk/res/android" > 
 
 <button 
  android:layout_ Width= "Fill_parent" 
  android:layout_height= "wrap_content" 
  android:text= "@string/add"/> 
 
 < Button 
  android:layout_width= "fill_parent" 
  android:layout_height= "wrap_content" 
  android:text= "@ String/delete "/> 
 
</merge> 


Now, when you add the layout file (using the <include/> tag), the system ignores the < merge/> node and adds two button directly to
Replaces the <include/> node.

As little as possible.

To speed up the view, reduce unnecessary code from those that invoke frequent activities. Start drawing in the OnDraw () method, it will give you the largest
Benefit. Particularly low, you should also reduce the memory allocations in the OnDraw () method because any memory allocations can result in memory recycling, which will
Cause discontinuity. Objects are allocated between initialization or animation. Never allocate memory while the animation is running.


On the other hand, you need to reduce the overhead in the OnDraw () method and call the OnDraw () method only when needed. Usually the invalidate () method calls the
OnDraw () method, thus reducing unnecessary calls to invalidate (). If possible, the overloaded version that calls it is the invalidate with parameters ()
Method rather than the parameterless invalidate () method. The method with the parameter invalidate () can make the draw process more efficient, and reduce the pair falling on the rectangle
The outer view of the range (the area specified by the parameter) does not need to be redrawn.

Note, the three overloaded versions of Invalidate () are:
1, public void invalidate (Rect dirty)
2, public void invalidate (int l, int t, int r, int b)
3. public void Invalidate ()


Another high cost operation is the layout process (layout). Any time you call the Requestlayout () method on the view, the Android UI framework
All need to traverse the entire view tree to determine the size of each view they occupy. If there are any conflicts during the measure process, you may iterate over multiple
The view tree. UI designers sometimes create deeper viewgroup to achieve some effect. But these deep view trees can cause efficiency
Problem. Make sure your view tree level is as shallow as possible.


If you have a complex UI design, you should consider designing a custom ViewGroup to implement the layout process. Unlike the built-in view control,
Custom view is able to assume the size and shape of each of its child view, while avoiding the measure process for each child view. Piechart
Shows how to inherit the ViewGroup class. Piechart has a child view, but it never measure them. Instead, it is based on its own layout algorithm
To set the size of each child view directly.

As shown in the following code:

/** * Custom view that shows a pie chart and, optionally, a label. * * public class Piechart extends ViewGroup {...////measurement functions. 
 This is example uses a simple heuristic:it assumes that//the pie chart should is at least as wide as its label. 
 @Override protected int Getsuggestedminimumwidth () {return (int) mtextwidth * 2; 
 @Override protected int Getsuggestedminimumheight () {return (int) mtextwidth; @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {//Try for a width of based on O 
 
  ur minimum int minw = Getpaddingleft () + getpaddingright () + getsuggestedminimumwidth (); 
 
  int w = Math.max (MINW, Measurespec.getsize (Widthmeasurespec));  Whatever the ' width ends up being ', ask for a ' height ' would let the ' pie//get as big as it can int minh = (W- 
  (int) mtextwidth) + getpaddingbottom () + getpaddingtop (); 
 
  int h = math.min (Measurespec.getsize (Heightmeasurespec), Minh); SetMeasureddimension (W, h); @Override protected void OnLayout (Boolean changed, int l, int t, int r, int b) {//Do nothing. Do don't call the superclass method--that would start a layout pass//To this view ' s children. 
 Piechart lays out it children in onsizechanged (). @Override protected void onsizechanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, old 
 
  h); Set dimensions for text, pie chart, etc.////account for padding ...//Lay out of the child view T 
  Hat actually draws the pie. Mpieview.layout ((int) mpiebounds.left, (int) mpiebounds.top, (int) mpiebounds.right, (int) Mpiebounds.botto 
  m); 
 
  Mpieview.setpivot (Mpiebounds.width ()/2, Mpiebounds.height ()/2); 
  Mpointerview.layout (0, 0, W, h); 
 Ondatachanged (); 

 } 
 
}


Using hardware acceleration

After Android version 3.0, the Android 2D graphics library can be accelerated using the GPU (graphics processing unit) on most Android devices. GPU Hardware
Acceleration can greatly optimize most applications, but it is not the best choice for each application. Android Framework to give you whether in the application
Use hardware to accelerate the control force.

It is worth noting that we have to manually set the application API level to 11 or higher in the configuration file, that is, configure the following in Androidmanifest.xml:

 <USES-SDK android:targetsdkversion= "one"/>

Once you turn on hardware acceleration, you may not see an increase in efficiency. Mobile GPUs is good at handling specific tasks, such as scaling, rotating,
Pan the picture. It also has some tasks that are not good at processing, such as drawing a line or curve. As the saying goes, make the best of the GPU
Deal with the tasks it specializes in, and reduce the ability to handle vulnerable tasks.


In the Piechart example, for example, drawing a circle is relatively resource-intensive. The redraw caused by each rotation causes the UI to slow down.
The workaround is to have the view render the circle and set the view's LAYER TYPE property to Layer_type_hardware, so the GPU
Ability to cache static pictures. The view in the example exists as an inner class of the Piechart class, reducing the code overhead to implement this method.

Private class Pieview extends View {public 
 
 Pieview (context) { 
  super (context); 
  if (!isineditmode ()) { 
   setlayertype (view.layer_type_hardware, null); 
  } 
 } 
  
 @Override 
 protected void OnDraw (Canvas Canvas) { 
  super.ondraw (Canvas); 
 
  for (Item it:mdata) { 
   mpiepaint.setshader (it.mshader); 
   Canvas.drawarc (Mbounds, 
     360-it.mendangle, 
     it.mendangle-it.mstartangle, 
     True, mpiepaint); 
  } 
 
 @Override 
 protected void onsizechanged (int w, int h, int oldw, int oldh) { 
  mbounds = new RECTF (0, 0, W, h) ; 
 } 
 
 RECTF mbounds; 
} 


After the change, the PieChart.PieView.onDraw () method is invoked only the first time the view is displayed. In the application's other
Time, the drawn image will be cached as a picture, and the GPU will rotate the image whenever it is redrawn.


Yet this is only a compromise. Caching a picture as a hardware layer causes the video memory overhead, while the video memory is a restricted
Resources. For this reason, on the final version of Piechart.pieview, the Layer Type property is set only when the user slides
Layer_type_hardware. At other times, just set its LAYER TYPE attribute to Layer_type_hardware, which
Allows the GPU to stop caching pictures.


Finally, don't forget to analyze your code. The optimization technique on one view may have a bad effect on other view.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.