Android development performance optimization summary (1)

The development of Android apps must first pay attention to a good user experience. If a software freezes seriously, is not smooth, and often crashes, it will bring users a very bad experience and lose users.
In the actual development and learning, I summarized the optimization of Android performance for your reference and exchange.

The performance problems of the app are reflected in many aspects, such as the slow startup speed for the first time, or the slow speed of entering a certain interface; the animation execution process is not smooth, or the animation execution freezes for a long time; The execution speed of a specific interface customized by the program is slow; there is no response (ANR) for a long time when responding to a certain user event; when operating the database, the addition, deletion, modification and query of a large amount of data is performed, and the execution speed is slow; the file is frequently read and written, and the cache file is too large Causes freezes; after the application has been running for a long time, freezes occur randomly.

There may be more than one reason for the above problems. In some cases, it may not be a problem with the application itself, or it may be a problem with other layers of the system, but it is only reflected in the application layer. Therefore, when developers deal with performance problems, the first thing they need to do is to judge whether the performance problem is caused by the application itself, and then prescribe the right medicine; but sometimes the logic of the application itself is normal, but due to insufficient hardware configuration of the system, abnormalities are caused. At this time, it is necessary to adopt some more precise methods to optimize performance according to product or project requirements to make up for the lack of hardware configuration.

The following summarizes some methods of application performance optimization from several different angles.

1. Programming ideas

Performance optimization at the application layer can usually be considered from the following aspects:

  1. Understand the compilation principles of programming languages, and use efficient coding methods to improve program performance syntactically;
  2. Use reasonable data structures and algorithms to improve program performance, which is often the key to program performance;
  3. Pay attention to interface layout optimization;
  4. Use multi-threading, cache data, lazy loading, early loading and other means to solve serious performance bottlenecks;
  5. Reasonably configure the upper limit and utilization rate of virtual machine heap memory to reduce the frequency of garbage collection;
  6. Reasonable use of native code;
  7. Reasonably configure the database cache type and optimize the SQL statement to speed up the reading speed, and use transactions to speed up the writing speed;
  8. Use tools to analyze performance problems and find performance bottlenecks;
    of course, there must be many other performance optimization methods, and here are only some commonly used methods.

2. Programming skills
There are some tips on improving application performance on the Android official website. Here is a brief list and some of my own experience in actual development. The details can be obtained from the official website documentation .
It should be noted that the optimization techniques listed in the article are mainly some minor performance improvements, and the overall performance of the program still depends on the business logic design of the program, the data structure and algorithm of the code. R&D personnel need to apply these optimization techniques to the usual coding process, which will have a great impact on performance.
To write efficient code, you need to follow two principles:
do not perform unnecessary operations;
do not allocate unnecessary memory;
the two principles are respectively aimed at CPU and memory, and save CPU and memory resources as much as possible under the premise of completing necessary operations. The execution efficiency should be high. Simply saying this sounds empty, after all, there is no unified standard to judge what is necessary and unnecessary, and it needs to be analyzed in combination with specific situations.
1. Avoid creating unnecessary objects
Creating objects has a cost. A generational garbage collector with a thread-level allocation pool for temporary objects can reduce allocation costs, but allocating memory is always more expensive than not allocating memory. Creating too many objects will cause poor performance. First, it takes time to allocate memory itself. Second, there is an upper limit on the heap memory usage when the virtual machine is running. When the usage reaches a certain level, garbage collection will be triggered. Garbage collection will make threads and even The entire process is suspended. It is conceivable that if objects are created and destroyed frequently, or the memory usage is high, the application will be severely stuck.
2. Reasonable use of static
If you don't need to access a field of an object, make the corresponding method static. The call speed will increase by about 15%-20%.
There are three main points to grasp:
If a method does not need to operate dynamic variables and methods at runtime, then the method can be set to static.
The constant field should be declared as "static final", because the constant will be stored in the static field initializer of the dex file and accessed directly, otherwise it needs to be initialized by some functions automatically generated at compile time at runtime. This rule is only valid for primitive types and String types.
Do not declare the view control as static, because the View object will refer to the Activity object. When the Activity exits, the object itself cannot be destroyed, which will cause memory overflow.
3. Avoid internal Getters/Setters
In object-oriented design, it is usually a good principle to use Getters/Setters for field access, but limited to hardware conditions in Android development, unless the field needs to be publicly accessed, otherwise if it is only a limited range of internal For access (such as access within a package), it is not recommended to use Getters/Setters. When JIT is turned on, direct access is 7 times faster than indirect access.
4. Use enhanced for loops
Prioritize the use of enhanced for loops in general to obtain higher efficiency; except for one case, that is, when traversing the ArrayList, using ordinary for loops is more efficient.
5. For private inner classes, consider using package access rights instead of private access rights.
The methods of private inner classes access the private member variables and methods of outer classes, which is grammatically correct, but the virtual machine does not directly access them at runtime. Instead, some package-level static methods will be automatically generated in the external class at compile time, and the internal class will call these static methods to access the private members of the external class during execution. In this case, there is an extra layer of method calls, and the performance is lost.
One way to solve this problem is to change the private members of the outer class to the package level, so that the inner class can be directly accessed, of course, the premise is that the design is acceptable.
6. Avoid using floating-point types
In Android devices, floating-point types are about twice as slow as integer data processing, so if integers can solve problems, don't use floating-point types.
Also, some processors have hardware multiplication but no division, in which case the division and modulo operations are implemented in software. In order to improve efficiency, you can consider directly rewriting some division operations as multiplication when writing calculation expressions, for example, rewrite "x / 2" as "x * 0.5".

7. Adopt <merge>optimized layout layers. Adopt <include>to share the layout.
8. Delay loading View. Use ViewStub to avoid some infrequent views being referenced for a long time and occupy memory.
9. Remove the default background of the Activity to improve the loading speed of the activity.
If you are sure that you are using an opaque background in your Activity, you can remove the Activity's default background.
In the code: getWindow().setBackgroundDrawable(null);
can also be set in the styles style file and configured in the Manifest file

 <style name="MyStyle" parent="AppTheme">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@null</item>  
 </style>

10. Use of cursor .
Pay attention to manage the cursor well, don't open and close the cursor every time, because opening and closing the cursor is very time-consuming.
Remember to close the cursor that is no longer used (usually executed in the finally statement block).
There is a situation where we cannot close the Cursor directly, which is the case in the CursorAdapter, but note that the CursorAdapter does not automatically close the Cursor when the Activity ends, so you need to close it manually in the onDestroy function .

protected void onDestroy() { 
      if (mAdapter != null && mAdapter.getCurosr() != null) { 
	      mAdapter.getCursor().close(); 
      } 
      super.onDestroy(); 
	}

11. When broadcasting BroadCast dynamic registration, remember to unregisterReceiver at the end of the caller's life cycle to prevent memory leaks.
12. Optimize the performance of ListView
items to reduce the level of controls and layouts used as much as possible; the background color is set to the same color as cacheColorHint; the layout of items in ListView is very important, and the controls and layouts used must be reduced as much as possible. RelativeLayout is an absolute weapon, through which you can reduce the level of layout. At the same time, it is necessary to reuse controls as much as possible, which can reduce the memory usage of ListView and reduce the number of GC when sliding. The background color of ListView is set to the same color as cacheColorHint, which can improve the rendering performance when sliding. The performance of getView in ListView is the key, and it should be optimized as much as possible here. The view should be reused in the getView method; complex logic calculations, especially database operations, cannot be done in the getView method, otherwise it will seriously affect the performance of sliding; when there are many data items in the ListView, consider pagination loading.
13. Pay attention to using the thread synchronization mechanism (synchronized) to prevent exceptions from occurring when multiple threads access an object at the same time.
14. Reasonable use of StringBuffer, StringBuilder, and String
In simple string concatenation, String is the most efficient, for example, String s = "hello" + "world";
but everyone should pay attention here, if your string is From another String object, the speed is not so fast, for example:
    String str2 = "This is";
    String str3 = "a";
    String str4 = "test";
    String str1 = str2 + str3 + str4;
StringBuilder is required here
. In a single thread, the performance of StringBuilder is higher than that of StringBuffer. Multi-threading needs to use StringBuffer for thread safety, because it is synchronized. Under normal circumstances, StringBuilder is generally used.
15. Try to use local variables.
The parameters passed when calling the method and the temporary variables created during the call are all stored in the stack (Stack), which is faster. Other variables, such as static variables, instance variables, etc., are created in the heap (Heap), which is slower. In addition, depending on the specific compiler/JVM, local variables may be further optimized.
16. Remember to close the stream object in time for I/O stream operations.
17. Use IntentService instead of Service
IntentService and Service are both a service, the difference is that IntentService uses a queue to add the requested Intent to the queue, and then starts a worker thread (thread) to process the Intent in the queue (in the onHandleIntent method), for For asynchronous startService requests, IntentService will process one and then process the second one. Each request will be processed in a separate worker thread, which will not block the main thread of the application. If there is a time-consuming operation, it is better to start it in the Service A new thread might as well use IntentService to handle time-consuming operations.
18. Use Application Context instead of Context in Activity.
Do not let objects with a long life cycle refer to activity context, that is, ensure that the object that refers to the activity has the same life cycle as the activity itself.
For objects with a long life cycle, you can use Application Context
instead of setting the Context object as static.
19. The objects in the collection should be cleaned up in time.
 We usually add the references of some objects to the collection. When we don’t need the object, we don’t clean up its references from the collection, so the collection will become bigger and bigger. . If the collection is static, the situation is even more serious.
20. Use of
Bitmap Pay attention to compressing larger Bitmaps before using them. When loading high-definition large images, you can consider using BitmapRegionDecoder.
Pay attention to recycle() in time for unused Bitmaps.
21. Use soft references (SoftRefrence) skillfully
 . After using the Bitmap, no reference to it is kept, so the Recycle function cannot be called. At this time, the clever use of soft references can make the Bitmap effectively released when the memory is running low. For an introduction to the Java reference mechanism, you can read my other blog: Four reference types of Java objects
22. Try not to use the entire large image as a resource file, try to use 9path images
. Environment), other resource maps, and .9 maps should be placed under drawable-xxxx, and pictures that need to be copied to the SD card of the mobile phone should be placed in the assets directory; using webp pictures instead of png can greatly reduce the picture size.
23. Understand and use library functions
The Java standard library and Android Framework contain a large number of efficient and robust library functions, and many functions are also implemented natively, which is usually much more efficient than the code we use to implement the same function in Java. So being good at using system library functions can save development time and is not prone to errors.
24. Regarding WebView,
remember to destroy WebView when Activity or Fragment is destroyed

@Override
    protected void onDestroy() {
        if (webView!= null) {
            webView.destroy();
            webView= null;
        }
        super.onDestroy();
    }

25. Reasonable use of JNI
and Android NDK to develop applications using Native code is not necessarily more efficient than programming in Java language. First, there are costs associated with Java-Native transitions, and the JIT cannot optimize outside of these boundaries. If you're allocating native resources (memory on the native heap, file descriptors, or any other element), it can be much more difficult to arrange for these resources to be reclaimed in a timely manner. You also need to compile your code for each architecture you want to run it on. You may also need to compile multiple versions of the so library for different CPU architectures.
Native code is primarily suitable for cases where you want to port an existing native code base to Android, not for "accelerating" parts of an Android application written in the Java language.
26. Make good use of the exception capture mechanism.
Java provides a try-catch syntax block to catch code exceptions. In daily development, we cannot fully consider many situations, and exceptions may occur at any time. A robust code should include exception handling Mechanism, reasonable use of try-catch can avoid the problem of many applications crashing, and can also help developers quickly locate the problem.
27. Power consumption optimization
The power consumption of the app is mainly reflected in:
1. Frequent object creation, time-consuming operations or complex calculation operations
2. The application actively wakes up the screen, or controls the screen to always be on, and actively increases the screen brightness
3. Background timing Tasks and services run for a long time
. Developers can consider how to optimize these operations to save power based on these three points.

3. Use tools to analyze application performance
(this part has more content, please see "Android Development Performance Optimization Summary (2)" for details .

Guess you like

Origin blog.csdn.net/gs12software/article/details/51173392