The improved layout performance layout is the core component of the android application. It directly affects the user experience. If you do not implement it well, the layout you implement may cause the application memory to be tight, as a result, UI rendering slows down. The Android SDK provides some tools to help us find out the performance problems in our layout. after learning the following knowledge points, you will be able to make your application run smoothly, occupies a small amount of memory to optimize the layout structure
The common misunderstanding is that using the basic layout structure can bring the most efficient layout effect. However, any control and layout added to the application must be initialized, painted, and rendered. For example, using nested linearlayout can lead to a deep view hierarchy. Moreover, nested linearlayout is used, especially when you use
Layout_weightAttribute is extremely performance-consuming, because each subcontrol of linearlayout must be measured twice. This is very important when your layout needs to be rendered repeatedly, such as when you use girdview or listview.
Check your layout in detail
The android SDK tool set contains a tool named hierarchy viewer to help analyze the rendering performance of the layout when our applications are running, the hierarchy Viewer tool can help you find the performance bottleneck of the layout file we have written.Hierarchy Viewer allows us to work by selecting a process running on a mobile phone or simulator, and then display the control tree of the interface on which users interact in the process, the traffic lights of each block indicate its measurement, layout, and drawing performance, helping you identify potential problems.
For example, figure-1 shows the layout of an item in listview, a small image and two lines of text. The performance advantage of layout optimization that requires multiple rendering will multiply.
Figure 1. Conceptual layout for an item inListView.
The hierarchyviewer tool can be found and used in the <SDK>/tools/directory. When you open it, it displays the devices connected to your computer and their running components, click the load view hierarchy button to display the layout hierarchy of the selected component.
Figure 2.Layout
Hierarchy for the layout in Figure 1, using nested instancesLinearLayout.
Figure 3. Clicking
A hierarchy node shows its performance times. Through this, we can know the time spent measuring, layout, and drawing each control at each level, from which we can find the points we need to optimize.
Fix your layout
The use of nested layout files reduces the rendering performance of the layout. The use of a single flat layout may improve the performance, so that the layout is lighter than the width and depth. The relative layout of relativelayout can make the layout level lighter.
Figure 4. Layout hierarchy for the layout in figure 1, using RelativeLayout.Now rendering a list item takes:
- Measure: 0.598 Ms
- Layout: 0.110 Ms
- Draw: 2.146 Ms
Using relativelayout can improve the performance, but you can improve the performance when you need to display thousands of such la S.
This time difference is mostly because layout_weight is used in the design of linearlayout, which reduces the measurement speed. We should properly use every layout. When using linearlayout, you need to think about whether it is really necessary to find that hierarchy does not work on a real machine, as if it only works on a simulator, I don't know if it's my problem.
Use lint
We can use the lint tool on the layout file to find possible hierarchical optimization points of the view. Lint has replaced the layoutopt tool and has many better features. some lint rules:
Use composite canvas-using composite canvas in a linearlayout containing imgeview and textview is more efficient
If a layout has a child control but no sibling control, and it is not a root layout, not a scrollview, and has no background, you can remove it.
If a layout does not contain a child control and has no background, it will not be displayed on the interface. We can remove it.
Use the flat layout relativelayout or gridlayout whenever possible
If a framelayout is a root layout with no background and no padding, replace it with the merge tag.
We can easily use lint in eclipse. We can use lint for a project and layout file to analyze the areas that need optimization and obtain the suggestions provided by lint.
Reuse layout with <include/>
Although Android provides a variety of widgets to build small and reusable interactive elements, you may need a larger reusable component unit to meet a special layout requirement, you can use
<include/>And
<merge/>Label to embed another Layout Unit into the current layout unit.
Reusable layout is a particularly useful method for you to build reusable composite la s, such as a yes/no button, a custom progress bar containing descriptive information. This means that any element in your application can extract multiple la S, manage them separately, and then include them in their respective la S. Therefore, when you create a private UI component of the layout to customize a view, you can reuse a Layout Unit to achieve this more easily. Create a reusable Layout Unit
When you know that you need to reuse the layout, you can create a new XML layout file to define it. Below is a layout unit to be reused, titlebar layout File
< FrameLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height= "wrap_content" android:background= "#FF000000" > <ImageView android:layout_width= "wrap_content" android:layout_height ="wrap_content" android:src ="@drawable/titlebar" android:contentDescription ="@string/app_name" /></ FrameLayout>
If you want to make your Layout Unit reusable in every layout, the root tag should be appropriate.
Use the <include/> label
You can use the <include/> label to add reusable components in the layout.
< LinearLayout 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:paddingBottom= "@dimen/activity_vertical_margin" android:paddingLeft= "@dimen/activity_horizontal_margin" android:paddingRight= "@dimen/activity_horizontal_margin" android:paddingTop= "@dimen/activity_vertical_margin" tools:context= ".MainActivity" android:orientation= "vertical" > <include layout= "@layout/titlebar"/> <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="@string/hello_world" /></ LinearLayout>
You can also re-write the Reusable Component in the current layout.
Android: Layout _*Attribute
<include android:id ="@+id/news_title" android:layout_width ="match_parent" android:layout_height ="match_parent" layout= "@layout/titlebar" />
Use the <merge/> label
<Merge/> labels can help you eliminate redundant view groups in your view hierarchy, when one layout contains another layout. When your main layout is a vertical structure of linearlayout that contains two consecutive views that can be reused by other layout, two reusable views in the layout need their respective root views. When using another linearlayout to act as the Root View of reusable views, this will cause the linearlayout of a vertical structure to be nested in the linearlayout of another vertical structure. The nested linearlayout has no practical effect in addition to slowing down your UI rendering speed, to avoid this, you can use the <merge/> label as the Root View of reusable layout components.
<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>
Similarly, the <include/> label is used to add the button to the layout. In this way, the android system does not actually store the <merge/> label, but directly places the two buttons in the layout, avoid unnecessary nesting. In addition, you must note that <merge/> can only serve as the root node of the layout. When you need to include other layout components, the layout itself uses <merge/> as the root node, XML to be imported
Place layout in viewgroup, and set attachtoroot to true.
Use viewstub
Sometimes there may be some complex views that are rarely used in our applications, which may be the details of a list item, a progress indicator, or information that does not need to be processed, when the view is used, the view is loaded instead of when the application is started. In this way, the application can effectively reduce memory usage and accelerate the rendering speed of the view.Define a viewstub
Viewstub is a lightweight view, which is a widget that does not occupy the layout, is invisible, and occupies a very small amount of resources.
<ViewStub android:id ="@+id/stub_import" android:layout_width ="fill_parent" android:layout_height ="wrap_content" android:layout_gravity ="bottom" android:inflatedId ="@+id/item_details_import" android:layout ="@layout/item_details" />
Item_details.xml
<? xml version= "1.0" encoding = "utf-8"?>< LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width= "match_parent" android:layout_height= "match_parent" android:orientation= "vertical" > <TextView android:id ="@+id/tv_stub_item_details" android:layout_width= "wrap_content" android:layout_height ="wrap_content" android:text ="@string/item_details" /></ LinearLayout>
Once visible/inflated, viewstub is not part of the layout structure and replaced by its inflated layout (item_details.xml). viewstub can only be inflate once, after that, the viewstub object will be left blank, and viewstub will become unavailable, and the inflated layout cannot be controlled, viewstub does not support the inflated layout with <merge/> labels.Use background threadAsynctaskUpdate the UI by using viewholder
Use asynctask
The rendering and loading of the UI are all running in the main thread of the android program. If the main thread of the UI is blocked for more than 5 s, the application will not respond, which will bring an extremely bad experience to users, for example, retrieving an image from the server and other time-consuming operations may cause no response to our application. In this case, we can use the background thread asynchronous asynctask class to load the data update UI in the background.
// Using an AsyncTask to load the slow images in a background threadnew AsyncTask<ViewHolder, Void, Bitmap>() { private ViewHolder v; @Override protected Bitmap doInBackground(ViewHolder... params) { v = params[0]; return mFakeImageLoader.getImage(); } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); if (v.position == position) { // If this item hasn't been recycled already, hide the // progress and set and show the image v.progress.setVisibility(View.GONE); v.icon.setVisibility(View.VISIBLE); v.icon.setImageBitmap(result); } }}.execute(holder);
After android3.0, aynsctask has a new feature. You can execute multiple background tasks on a multi-core CPU at the same time, but you need to call
Executeonexecutor () method to replaceExecute () method using viewholder
When we slide the listview, The findviewbyid () method is frequently called, which will reduce the performance of our program. Even if the adapter can return a rendered view that has been recycled, it still needs to find the elements contained in the view and update them, you can use the "view Hodler" design mode to solve the performance problems caused by repeated use of findviewbyid ().
Viewhodler can store every element in convetview. You only need to directly retrieve the element from viewhodler next time, instead of repeating the findviewbyid () part of the code snippet.
@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = mInflater.inflate(R.layout.applist_item, null);holder = new ViewHolder();holder.icon = (ImageView) convertView.findViewById(R.id.applist_item_iv_appicon);holder.name = (TextView) convertView.findViewById(R.id.applist_item_tv_appname);holder.pk = (TextView) convertView.findViewById(R.id.applist_item_tv_apppk);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}holder.icon.setImageDrawable((Drawable) datalist.get(position).get("icon"));holder.name.setText((String) datalist.get(position).get("name"));holder.pk.setText((String) datalist.get(position).get("pk"));return convertView;}static class ViewHolder {ImageView icon;TextView name;TextView pk;}