Introduction:

Google’s official Android performance optimization model short video course is to learn Android performance optimization excellent course, has been updated to the fifth season. Youku address

The main content

  • Performance optimization for Android
  • Memory leak analysis tool MAT
  • Improve the maintainability of applications

The specific content

As a mobile device, Android devices have certain limitations in both memory and CPU performance, which also means that Android programs cannot use memory and CPU resources without limit. Excessive use of memory may lead to OOM, and excessive use of CPU resources may lead to sluggish or even unresponsive phones (ANR). This also puts higher demands on developers. This chapter mainly introduces some effective performance optimization methods. It mainly includes layout optimization, drawing optimization, memory leak optimization, response speed optimization, ListView optimization, Bitmap optimization, thread optimization, etc. ANR log analysis method is also introduced.

Performance optimization for Android

Layout optimization
  • The idea of layout optimization is to minimize the level of layout files so that there is less work to draw the interface and the performance of the application is naturally higher.

Remove useless controls and hierarchies

  • You can optionally use a ViewGroup with a lower performance, so if you can use either a Linearlayout or a RelativeLayout layout, that’s the Linearlayout, because it’s kind of complicated, Its layout process takes more CPU time.

In some cases LinearLayou won’t be able to use LinearLayou, so you need to use a RelativeLayout. In this case, using a RelativeLayout is recommended, because nesting a ViewGroup increases the layout level and reduces application performance.

  • Use include tags, merge tags, and viewstubs
    • The include tag
    • The merge tag
    • ViewStub

When a ViewStub is loaded using the setVisibility or inflate method, it is replaced by its internal layout and is no longer part of the overall layout structure.

Draw the optimization

The View’s onDraw method avoids doing a lot of work:

  • Do not create a large number of local objects in onDraw, because the onDraw method will be called frequently, which will generate a large number of temporary objects in a flash, not only too much memory will cause the system to frequent GC, reducing the efficiency of program execution.
  • OnDraw also does not need to do time-consuming tasks, nor can it perform thousands of loops. Although each loop is lightweight, a large number of loops can still eat into the CPU’s time slice, which can make the View’s drawing process not smooth. According to Google’s official criteria, a View drawing at 60 FPS is optimal, which requires drawing time of no more than 16ms(1000/60) per frame. So keep the onDraw method as simple as possible.
Memory leak optimization

Memory leakage is one of the most common mistakes to make. There are two main aspects of memory leak optimization. One is to avoid writing code with memory leaks during development, and the other is to use analysis tools such as LeakCanary or MAT to find out potential memory leaks and solve them.

  • Memory leaks caused by static variables

For example, inside an Activity, a static Conext references the current Activity, so the current Activity cannot be released. Or a static variable that holds the current Activity and still can’t release it when it needs to release it.

  • Memory leaks caused by singleton mode

For example, the singleton pattern holds the Activity, and there is no unregistered action. Because the singleton pattern has the same life cycle as an Application, it has a longer life cycle than an Activity, which causes the Activity object to fail to be released in a timely manner.

  • Memory leak caused by property animation

Property animations have a class of infinite looping animations. If you play one of these animations in an Activity and don’t stop it in onDestroy, the animation will keep playing and the View of the Activity will be held by the animation, which in turn holds the Activity. As a result, the Activity cannot be released. The solution is to stop the animation by calling animator.cancel() in the Activity’s onDrstroy.

Response speed optimization and ANR log analysis

The core idea of response speed optimization is to avoid doing time-consuming operations in the main thread and put time-consuming operations in other threads to execute. An ANR is triggered when an Activity fails to respond to a screen touch or keyboard input event for 5 seconds, and when the BroadcastReceiver has not completed its operation for 10 seconds.

When ANR occurs in a process, the system creates a testamp. TXT file in the /data/ ANR directory, which can be analyzed to locate the cause of ANR.

As an example of how to analyze a file, first add the following code to onCreate() to make the main thread wait for a lock, and then click return to return 5 seconds later to see ANR.

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   // The following code is designed to simulate an ANR scenario to analyze logs
   new Thread(new Runnable() {
       @Override
       public void run(a) {
           testANR();
       }
   }).start();
   SystemClock.sleep(10);
   initView();
}
/** * The following two methods are used to simulate a slightly harder to find ANR */
private synchronized void testANR(a){
   SystemClock.sleep(3000 * 1000);
}
private synchronized void initView(a){}
Copy the code

ANR will appear, then export the /data/ ANR /straces. TXT file. Because of the content, only the key parts are posted:

DALVIK THREADS (15):
"main" prio=5 tid=1 Blocked
  | group="main" sCount=1 dsCount=0 obj=0x73db0970 self=0xf4306800
  | sysTid=19949 nice=0 cgrp=apps sched=0/0 handle=0xf778d160
  | state=S schedstat=( 151056979 25055334 199 ) utm=5 stm=9 core=1 HZ=100
  | stack=0xff5b2000-0xff5b4000 stackSize=8MB
  | held mutexes=
  at com.szysky.note.androiddevseek_15.MainActivity.initView(MainActivity.java:0)
  - waiting to lock <0x2fbcb3de> (a com.szysky.note.androiddevseek_15.MainActivity) 
  - held by thread 15
  at com.szysky.note.androiddevseek_15.MainActivity.onCreate(MainActivity.java:42)
Copy the code

As you can see from this paragraph, the final location of the ANR occurs in line 42 of the ManiActivity. The initView method is waiting for a lock < 0x2FBCB3de > whose type is a MainActivity object. The lock is already held by the thread whose id is 15(tid=15). Now let’s go to thread 15.

"Thread-404" prio=5 tid=15 Sleeping | group="main" sCount=1 dsCount=0 obj=0x12c00f80 self=0xeb95bc00 | sysTid=19985 nice=0 cgrp=apps sched=0/0 handle=0xef34be80 | state=S schedstat=( 391248 0 1 ) utm=0 stm=0 core=2 HZ=100 | stack=0xe2bfe000-0xe2c00000 stackSize=1036KB | held mutexes= at java.lang.Thread.sleep! (Native method) - sleeping on <0x2e3896a7> (a java.lang.Object) at java.lang.Thread.sleep(Thread.java:1031) - locked <0x2e3896a7> (a java.lang.Object) at java.lang.Thread.sleep(Thread.java:985) at android.os.SystemClock.sleep(SystemClock.java:120) at com.szysky.note.androiddevseek_15.MainActivity.testANR(MainActivity.java:50) - locked <0x2fbcb3de> (a com.szysky.note.androiddevseek_15.MainActivity)Copy the code

Sleep (3000 * 1000); sleep(3000 * 1000); sleep(3000 * 1000) TestANR (). The last line shows that locked< 0x2FBCB3de > is the lock object for which the main thread is waiting.

ListView optimization and Bitmap optimization

ListView/GridView optimization:

  • Use the ViewHolder to avoid time-consuming operations in the getView.
  • Secondly, the task execution frequency is controlled by the sliding state of the list, for example, a large number of asynchronous tasks are not and open when sliding fast.
  • Finally, try turning on hardware acceleration to make the ListView slide more smoothly.

Bitmap optimization: The main purpose is to sample and display images as needed. Please refer to Chapter 12 for details.

Thread optimization

The main idea is to use Thread pools to avoid large numbers of threads. Thread pools can reuse internal threads, avoiding the performance overhead of thread creation and destruction. At the same time, thread pool can effectively control the maximum number of concurrent threads, so as to avoid the blocking phenomenon caused by a large number of threads preempting system resources. Refer to Chapter 11 for details.

Some performance optimization tips
  • Avoid creating too many objects, especially in methods like loops and onDraw.
    1. Do not use enumerations too much. Enumerations take up more memory than integers. How to use annotion instead of Enum in Android
  • Constants are modified with static final;
  • Use android-specific data structures such as SparseArray and Pair for better performance;
  • Use soft and weak references appropriately;
  • Using memory cache and disk cache;
  • Use static inner classes as much as possible to avoid memory leaks caused by non-static inner classes implicitly holding external classes.

Memory leak analysis tool MAT

MAT Eclipse Memory Analyzer is a Memory leak analysis tool. Download it and unzip it. Download address www.eclipse.org/mat/downloa… Here is a brief description. I didn’t do this manually, just for the record, because Now Android Studio can analyze hprof files directly.

You can manually write code that causes a memory leak, then open the DDMS, then select the process you want to analyze, and then click the Dump HPROF file button. Wait a little bit to generate a file. This file cannot be recognized directly by MAT. You need to use the tools in the Android SDK to convert the format. The tool is in the platform-conv folder

Hprof-conv File name to be converted File name of the output file name The signature of the file name is the package name.

Then open MAT and open the converted file through the menu. Here are two commonly used:

  • Histogram: The quantity and memory occupation of different types of buffers in memory can be intuitively seen.
  • Dominator Tree: Memory leak analysis is done by sorting objects in memory from largest to smallest order and analyzing references between objects.

When analyzing memory leaks, you need to analyze the memory information in the Dominator Tree, which is not displayed directly. You can troubleshoot the memory information in descending order. If a leak occurs, right-click Path To GC Roots-> Exclude Wake /soft references. You can see what object is ultimately causing the failure to release. The reason we excluded soft and weak references is that, in most cases, both types can be collected by the GC, so there is almost no memory leak.

The search function can also be used here. If we manually simulate a memory leak and the leaking object is an Activity, we will find many Activit objects if we exit the rewind loop several times.

Improve the maintainability of applications

Improve readability
  • Naming conventions
  • Typography between code should leave reasonable white space to distinguish between different code blocks
  • Add comments for very critical code.
Hierarchy of code

Do not put a piece of business logic in a method or a class all implementation, it should be divided into several sub-logic, and then each sub-logic does its own thing, so that the code is hierarchical, which can improve the scalability of the program.

Program extensibility

Because many times during development there is no guarantee that requirements that have been made will not be changed in later releases, it is important to always keep extension in mind when writing programs, and consider what needs to be changed if the logic changes later, and how to reduce the amount of work in future changes. And extensible programming can make the program have good extensibility.