Android Performance Optimization strategy

Source: Internet
Author: User
Tags try catch

This article is mainly for the performance optimization of Google launched a model for an entire finishing ... Mainly in the specific optimization techniques, as for the 60fps, drop frame, GC, memory jitter, threshold value ... And so on, the concept of these performance terms does not do a long summary, please check ...

This article extends from the following points ...

Draw/Render

optimize the structure of the layout
    • Avoid complex view hierarchies. The more complex the layout of the more bloated, the more prone to performance problems, find the most resource-saving way to display nested content;
    • Try to avoid using relative layout relativelayout at the top level of the view level. Relative layout relativelayout is more resource-intensive because a relative layout relativelayout requires two measurements to ensure that it handles all of the layout relationships, and this problem is accompanied by the increase in relative layout relativelayout in the view hierarchy. and become more serious;
    • Layout hierarchy It is recommended to use linear layout linearlayout instead of relative layout relativelayout because the linear layout linearlayout performance is much higher; it does require relative layout relativelayout for the branch. You can consider a more optimized grid layout GridLayout, which has preprocessed the branch view relationship and avoids the problem of two measurements;
    • Relatively complex layout is recommended to adopt relative layout relativelayout, relative layout relativelayout can easily realize the layout of linear layout linearlayout nesting can be realized;
    • The reusable components are extracted and reused with the include tag. If the UI of multiple places is applied to a layout, it is written as a layout part, which facilitates the reuse of each UI;
    • Use the Merge tab to reduce the nesting level of the layout;
    • Remove the unwanted invisible background. There are multi-layered background color layout, only the top level of the user visible to the color can be, other users invisible bottom color may be removed, reduce invalid drawing operations;
    • Try to avoid using the Layout_weight property. Using a linear layout that contains the Layout_weight attribute linearlayout each subassembly needs to be measured two times and consumes too much system resources;
    • The layout structure of the reasonable interface should be wide and shallow, not narrow and deep;
Optimizing processing Logic
    • Load views on demand. Some of the less reusable views of resource consumption, can wait until the time needed to reload, improve UI rendering speed;
    • Use the viewstub tag to load some less commonly used layouts;
    • Dynamic inflation view performance is better than using Viewstub label setvisiblity performance, of course, some features of the implementation of Viewstub label more appropriate;
    • Try to avoid unnecessary resource operation and save valuable computing time;
    • Avoid heavy work on the UI thread. resource-intensive operations (such as IO operations, network operations, SQL operations, list refreshes, etc.) consume resources using the background process to implement, can not occupy the UI thread, the UI thread is the main thread, the main thread is the key to keep the program smooth, should only operate those core UI operations, such as processing view properties and drawing;
    • Minimize the wake-up mechanism. We often use broadcasts to receive messages and events that are expected to respond, but too much of the response exceeds our own requirements, which consumes the extra performance and resources of Android devices. Therefore, the wake-up mechanism should be minimized, and when the application does not care about the disappearance and the event, it shuts down the broadcast and chooses the Intent to respond carefully;
    • For low-end devices, such as 512M memory, dual-core CPUs, low resolution, to ensure that your application can meet different levels of equipment;
    • Optimize your app's startup speed. As soon as the app launches an app, the interface's feedback display can give the user a good experience. For faster start-up, you can defer loading some UI and avoid initializing code at the application level of the app.
UI Debugging Tools
  • Hierarchy View: Hierarchy View comes with the Android SDK and is often used to see if the view structure of the interface is too complex to understand which views are over-drawn and how to improve them.
  • Lint: Lint is a static code scanning tool that comes with ADT, which provides improved recommendations for XML layout files and unreasonable or risky modules in project code. The official tips on the actual use of Lint are listed below:
    • Contains useless branches, recommended removal;
    • Contains useless parent controls, recommended removal;
    • Warning the layout depth is too deep;
    • It is recommended to use compound drawables;
    • It is recommended to use the merge label;
      ......
  • systrace: Systrace in Android DDMS, can be used to track graphics, view and window information, to find some deep-seated problems. Very troublesome, limited, practical debugging I basically do not use;
  • Track: Tracks in Android Ddms, is a great way of tracking the construction of the view when the method is time-consuming, accurate to each function, whether it is applied functions or system functions, We can easily see where the frame is dropped and the call of all functions in that frame, to find out the problem points to optimize.
  • overdraw: By opening the "debug GPU over-Drawing" in the developer options of the Android device's settings app, you can view the over-rendering under all the interface and branch interface, which is easy to optimize;
  • GPU Rendering Mode analysis : By launching "GPU Rendering mode Analysis" in the developer option of the Android device's settings APP, you can get the time of rendering each frame of the last 128 frames, analyze performance and performance bottleneck;
  • Strictmode: By launching "strict Mode" in the developer options of the Android device Settings app, you can see which actions are being applied on the main thread for too long. When some actions violate strict mode, the surrounding border of the screen flashes red, and the relevant information of Strictmode is output to the LOGCAT log;
  • Animator Durationscale: To speed up or slow down the animation by opening "window animation Zoom"/"Transition Animation Zoom"/"Animation program Zoom" in the developer options of the Android device settings APP to see the acceleration or Whether there is a problem with slowing down the animation in the state;
  • Show hardwarelayer updates: Launches "Show hardware layer Updates" in the developer options of the Android device Settings APP, which appears green when the Flash hardware layer is updated. Using this tool allows you to see which layouts are not expected to update during the animation, so you can optimize them to get better performance from your app.
Memory/cpu

reduce the memory footprint of an object
    • use more lightweight data structures : Consider, for example, the use of Arraymap/sparsearray (Sparseboolmap,sparseintmap,sparselongmap, LONGSPARSEMAP) instead of traditional data structures such as HashMap. (http://hukai.me/android-performance-patterns-season-3/);
    • Avoid enumerations : It has been made clear on the Android website that you should avoid using enum on Android because it takes up much more memory than static constants. http://hukai.me/android-performance-patterns-season-3/;
    • Transmission of compressed gzip data;
    • resource files need to choose the right folder to store : we know hdpi/xhdpi/xxhdpi, etc. the images under different DPI folders will be processed by scale on different devices. For example, we only placed a picture of 100100 in the hdpi directory, then according to the conversion relationship, XXHDPI's mobile phone to refer to the image will be stretched to 200200. It is important to note that in this case, memory consumption is significantly increased. For images that do not want to be stretched, they need to be placed in the assets or nodpi directory.
    • lossy compression of images to reduce memory : use Tinypng;
    • reduce the memory footprint of the created bitmap : Zoom to bitmap or select decode format (transparency: argb_4444, no transparency: rgb_565).
Reusable Objects
    • reusable system comes with resources: The Android system itself contains a lot of resources, such as string/color/Picture/animation/style and simple layout, and so on, these resources can be directly referenced in the application. This will not only reduce the application's own load, reduce the size of the APK, but also to a certain extent, reduce the cost of memory, reusability is better. However, it is also important to keep an eye on the version differences of the Android system, which are very different from the performance of the various system versions, that do not meet the requirements, or that the application itself is built in.
    • Reuse of a control in a ListView
    • Reuse of Bitmap objects :
      • Using the LRU mechanism to cache the processed bitmap;
      • Use the advanced features of the inbitmap to increase the efficiency of the Android system in bitmap allocation and release (there are some differences in usage limits after 3.0 and 4.4). Using the Inbitmap property, you can tell the bitmap decoder to try to use an existing memory area, and the newly decoded bitmap will attempt to use the pixel data memory area occupied by bitmap in the heap. Instead of asking for memory to reapply an area to store bitmap. With this feature, even thousands of images will only need to occupy the memory size of the number of images that the screen can display.
    • avoid the creation of objects in the OnDraw method : Similar to OnDraw and other frequently called methods, it is necessary to avoid doing the creation of objects here, because he will quickly increase the use of memory, and it is easy to cause frequent GC, or even memory jitter;
    • StringBuilder: In some cases, the code will need to use a lot of string concatenation operations, it is necessary to consider the use of StringBuilder to replace the frequent "+";
    • avoid creating objects within a For statement ;
    • ...
avoid memory leaks for objects

The leakage of memory objects can cause some objects that are no longer in use to be released in a timely manner, which takes up valuable memory space and easily leads to an oom when there is insufficient free space to allocate memory.
Obviously, this also makes the memory area of each level of generation space smaller, the GC will be more easily triggered, prone to memory jitter, causing performance problems.
The latest Leakcanary open source control, can help us to find out the memory leak situation, more about leakcanary, please see here https://github.com/square/leakcanary (Chinese instructions for use. You can also use the traditional Mat tool to find memory leaks, please refer to here (convenient Chinese information)

  • Watch out for activity leaks.

    • Internal class references result in activity leaks:

      • The most typical scenario is an activity leak caused by handler, and if there are deferred tasks in handler or if the queue of tasks waiting to be executed is too long, it is possible that the activity will leak because handler continues to execute. The reference chain at this time is Activity, Handler, Message, MessageQueue, Looper. To solve this problem, you can execute the message in the Remove handler message queue with the Runnable object before the UI exits. or use static + WeakReference to achieve a referential relationship between the disconnected handler and the activity.
    • Activity context is passed to other instances, which can cause itself to be referenced and leak:

      • Internal classes are caused by leaks that occur not only in the activity, but in any other internal class where there is a need for special attention! We can consider using the static type's inner classes as much as possible, while using the weakreference mechanism to avoid leaks that occur as a result of mutual references.
  • Consider using application context rather than activity context;
  • Pay attention to the timely recovery of temporary bitmap objects
    • While in most cases we will increase the caching mechanism for bitmap, some of the bitmap need to be reclaimed in a timely manner. For example, a relatively large bitmap object that was created temporarily, after being transformed to get a new bitmap object, should reclaim the original bitmap as soon as possible, so that the space occupied by the original bitmap can be released faster.
      Special attention is given to the CreateBitmap () method provided in the bitmap class:
      The bitmap returned by this function may be the same as the source bitmap, and at the time of collection, it is necessary to check whether the source bitmap is the same as the return bitmap reference, and only if the source can be executed in unequal circumstances. The Recycle method of bitmap.
  • Note The listener's logoff:
    • There are many listeners in the Android program that need register and unregister, and we need to make sure that the listeners are unregister at the right time. Manually add the listener, need to remember to remove this listener in time.
  • Note the object leaks in the cache container:

    • Sometimes we put some objects into the cache container in order to improve the reusability of objects, but if these objects are not purged from the container in time, it is possible to cause a memory leak. For example, for a 2.3 system, if you add drawable to the cache container, because of the strong application of drawable and view, it is easy to cause the activity to leak. And from 4.0 onwards, there is no such problem. To solve this problem, we need to do a special encapsulation of the cache drawable on the 2.3 system, handle the problem of reference unbind, and avoid the situation of leaking.
  • Note the leakage of WebView:

    • Android WebView There is a lot of compatibility issues, not only the Android version of the different webview produced a great difference, in addition to different manufacturers shipped ROM inside WebView There is a great difference. More serious is the problem of a memory leak in the standard WebView, see here WebView causes memory Leak-leaks the parent Activity. So the usual way to solve this problem is to open another process for webview, through the aidl and the main process to communicate, webview the process can be based on the needs of the business to choose the right time to destroy, so as to achieve the full release of memory.
  • Note whether the cursor object closes in time:

    • In the program we often do the query database operation, but there are often inadvertently use the cursor after the case is not closed in a timely manner. These cursor leaks, repeated occurrences of the words will have a great negative impact on memory management, we need to remember to close the cursor object in a timely manner.
Optimization Strategy
  • Use large heap sparingly:

    • Android devices have different sizes of memory space depending on hardware and software settings, and they set the heap limit threshold for different sizes for the application. You can get the available heap size for your app by calling Getmemoryclass () . In some special scenarios, you can declare a larger heap space for your app by adding Largeheap=true properties under the Application tab of manifest. You can then get to this larger heap size threshold by Getlargememoryclass (). However, the claim for a larger heap threshold is intended for a small number of applications that consume large amounts of RAM (such as an editing application for a large picture). Don't be so easy because you need to use more memory to request a large heap size. Use the large heap only when you know exactly where to use a lot of memory and know why the memory must be preserved. Therefore, use the large heap property with caution. The use of additional memory space affects the overall user experience of the system and makes the GC run longer each time. The performance of the system is compromised when the task is switched. In addition, the large heap does not necessarily get a larger heap. On some severely restricted machines, the size of the large heap is the same as the usual heap size. So even if you apply for the large heap, you should check the actual heap size by executing getmemoryclass ().
  • Combine device memory thresholds with other factors to design the appropriate cache size:

    • For example, when designing the bitmap LRU cache for a ListView or GridView, the points to consider are:
      • How much memory space does the application have left?
      • How many images will be rendered to the screen at once? How many images need to be cached in advance so that they can be instantly displayed to the screen when quickly sliding?
      • What is the screen size and density of the device? A xhdpi device will require a larger cache than hdpi to hold the same number of images.
      • What is the size and configuration of the different pages for bitmap design, and how much memory will probably be spent?
      • How often is the page image accessed? Is there a part of it that is more frequent than other pictures with higher access? If so, you might want to save those most frequently accessed into memory, or set up multiple LRUCache containers for different groups of bitmaps (grouped by frequency of access).
  • onLowMemory()与onTrimMemory()
    Android users can switch quickly between different apps. In order for background applications to quickly switch to Forground, each background application consumes a certain amount of memory. Depending on the memory usage of the current system, the Android system decides to reclaim some of the background's application memory. If the background app is restored directly from the paused state to forground, it will be able to get a faster recovery experience, and if the background app is recovering from the kill state, it will appear slightly slower.

    • Onlowmemory (): The Android system provides callbacks to inform the current application of memory usage, and generally, when all background applications are killed, the Forground application receives a callback from Onlowmemory (). In this case, the non-essential memory resources of the current application need to be released as soon as possible to ensure that the system continues to run stably.
    • Ontrimmemory (int): The Android system also provides a callback for the Ontrimmemory () starting from 4.0, and all running applications receive this callback when the system memory reaches certain conditions. At the same time in this callback will pass the following parameters, representing different memory usage, received ontrimmemory () callback, you need to determine the type of parameters passed, reasonable choice to release some of its own memory, on the one hand, can improve the overall running smoothness of the system, It is also possible to avoid being judged by the system as a priority for applications that need to be killed. Describes the various callback parameters:

      • trim_memory_ui_hidden : All UI interfaces for your application are hidden, That is, the user clicks the home button or the back key to exit the app, which makes the app's UI completely invisible. At this point, you should release some non-visible resources.
      • When the program is running in the foreground, you may receive one of the following values returned from Ontrimmemory ():
        • trim_memory_run Ning_moderate : Your app is running and will not be listed as a kill. However, when the device is running in a low memory state, the system starts triggering a mechanism to kill the process in the LRU cache.
        • trim_memory_running_low : Your app is running and is not listed as a kill. However, when the device is running in a lower memory state, you should free up unused resources to improve system performance.
        • trim_memory_running_critical : Your app is still running, but the system has already killed most of the processes in the LRU cache, so you should immediately release all non-essential resources. If the system is not able to reclaim enough RAM, the system clears all the processes in the LRU cache and starts killing processes that were previously thought not to be killed, such as the one containing a running service.
    • You may receive one of the following values returned from Ontrimmemory () when the application process has retreated to the background while it is being cached:

      • TRIM_MEMORY_BACKGROUND: The system is running in a low memory state and your process is in the most vulnerable location in the LRU cache list. Although your application process is not in a high-risk state of being killed, the system may have started to kill other processes in the LRU cache. You should release the resources that are easy to recover so that your process can be preserved so that you can recover quickly when the user rolls back to your app.
      • TRIM_MEMORY_MODERATE: The system is running in a low memory state and your process is already close to the central location of the LRU list. If the system starts to become more memory intensive, your process is likely to be killed.
      • TRIM_MEMORY_COMPLETE: The system is running in a low-memory state and your process is in the most easily killed position on the LRU list. You should release any resources that do not affect the recovery status of your app.

        • Because the callback for Ontrimmemory () is added in API 14, you can use the onlowmemory callback for compatibility with older versions. Onlowmemory quite with Trim_memory_complete.
      • Note: While the system is starting to purge processes in the LRU cache, it first performs operations in the LRU order, but it also takes into account the memory usage of the process and other factors. The less-occupied process is more likely to be left.

  • Try catch some large memory allocations for operations:

    • In some cases, we need to evaluate the code that may have oom in advance, and for these potentially oom code, join the catch mechanism and consider trying a degraded memory allocation operation in the catch. For example decode bitmap, catch to Oom, you can try to increase the sampling ratio by one more times, try to decode again.
  • Resource files need to choose the right folder to store

  • Use static objects with caution:
    • Because static life cycles are too long and consistent with the application process, improper use is likely to cause object leaks, and static objects should be used with caution in Android.
  • Special attention is paid to the unreasonable holding of a single Case object:
    • Although the singleton pattern is simple and practical, it offers many conveniences, but because the life cycle of the singleton is consistent with the application, it is very easy to use the leakage of the object.
  • Cherish Services Resources
    • If your app needs to use the service in the background, unless it is triggered and performs a task, the service should be in a stopped state at other times. It is also important to note the memory leaks caused by stopping service failures after the service completes the task. When you start a service, the system tends to retain the service and keep the process in place. This makes the process expensive to run because the system has no way to free up the RAM space occupied by the service to other components, and the service cannot be paged out. This reduces the number of processes that the system can store into the LRU cache, which can affect the efficiency of switching between applications, and may even cause system memory usage to be unstable, thus failing to maintain all currently running service. It is recommended to use Intentservice, which will end itself as soon as possible after handling the tasks that have been confessed to it. For more information, please read running in a Background Service.
  • Optimize layout hierarchies and reduce memory consumption
    • The more flattened the layout of the view, the less memory is used and the more efficient it is. We need to try to ensure that the layout is flat enough to consider using a custom view when the system-provided view cannot be flat enough to achieve the goal.
  • Use "abstract" programming with caution

    • Many times, developers use abstract classes as "good programming practices," because abstractions can improve the flexibility and maintainability of code. However, abstraction leads to a significant additional memory overhead: they need the same amount of code to execute, and those code is mapping into memory, so if your abstraction doesn't have significant productivity gains, you should try to avoid them.
  • Use the Dependency Injection framework sparingly

    • Using frameworks like Guice or Roboguice to inject code to some extent simplifies your code.
      The code is much simplified. However, those injection frameworks perform many initialization operations by scanning your code, which will cause your code to require a lot of memory space to mapping code, and mapped pages will remain in memory for a long time. Unless it is really necessary, it is advisable to use this technique with caution.
  • Use multiple processes with caution:

    • Using multiple processes can run some components of the application in a separate process, which can expand the memory footprint of the application, but this technique must be used with caution, and most applications should not use multiple processes, on the one hand because the use of multiple processes will make the code logic more complex, and if used improperly, It may instead cause a significant increase in memory. When your application needs to run a permanent background task, and this task is not lightweight, you can consider using this technique.
    • A typical example is creating a music player that can be played back in the background for a long time. If the entire application is running in a process, there is no way to release the UI resources from the foreground while the background is playing. Applications like this can be cut into 2 processes: one for manipulating the UI and the other for the backend service.
  • Use Proguard to weed out unwanted code

    • Proguard can compress, optimize, and confuse code by removing unwanted code, renaming classes, domains and methods, and so on. Using Proguard can make your code more compact, which reduces the memory space required for mapping code.
  • Careful use of third-party libraries:

    • Many open Source library code is not written for the mobile network environment, if used on mobile devices, and not necessarily suitable. Even a library designed for Android requires special care, especially if you don't know what the library has done specifically. For example, one of the libraries uses the Nano Protobufs, and the other one uses the Micro Protobufs. This way, there are 2 ways to implement PROTOBUF in your application. Similar conflicts can occur in output logs, loading images, caches, and so on. Also do not import the entire library for 1 or 2 functions, and if you do not have a suitable library to match your needs, you should consider implementing it yourself rather than importing a chatty solution.
Measuring Tools
    • Memory Monitor: Keeps track of the changes in the entire app.
    • Heap Viewer: View the current memory snapshot to facilitate a comparative analysis of which objects may have been compromised.
    • Allocation Tracker: Trace the source of the memory object.
Power

Network and power consumption

A fully working radio consumes a lot of power, so you need to learn how to transition in different energy states, save power when the radio is not working, and try to minimize the delay associated with radio-wave power when needed.

The typical 3G radio network has three energy states:

    • Full power: Allows the device to operate at the maximum transfer rate when the wireless connection is activated.
    • Low power: An intermediate state in which the power consumption is almost 50% of the full power state.
    • Standby: Minimum energy state, no active or required network connection.

      Low power to full power takes about 1.5 seconds;
      Standby to full power takes about 2 seconds;
      Full power to low power takes about 5 seconds;
      Low power to Standby takes about 12 seconds;

Strategy
    • Prioritize time-consuming operations in a wireless network (video, File download ...) ):

      • Use of radio consumption less than the use of mobile traffic
    • The transfer of data using Prefetching (prefetching) and bundles (bundles) is done to minimize power consumption.

operation according to Battery state difference

Such as:

    • Charge status or charge more than 20% play video directly
    • When the battery is below 20%, give the prompt "please recharge ..."
    • ....
Wake-up work and power consumption

It is a contradictory choice to keep more power efficiently and to drive users to use your app to consume power. But we can use some better ways to balance the two.
Let's say you have a lot of social apps in your phone, and even when your phone is on standby, it's often woken up by these apps to check for new data syncing. Android will constantly turn off all kinds of hardware to extend the phone's standby time, first the screen will gradually darken until shut down, and then the CPU goes to sleep, all this is to save valuable power resources. But even in this state of sleep, most applications will still try to work, and they will constantly wake up the phone. One of the simplest ways to wake up a phone is to use the Powermanager.wakelock API to keep the CPU working and prevent the screen from darkening off. This allows the phone to be awakened, perform work, and then go back to sleep. Knowing how to get Wakelock is simple, but releasing wakelock in a timely manner is also very important, and improper use of wakelock can lead to serious errors. For example, the data return time of the network request is uncertain, which causes only 10s of things to wait for 1 hours, which will make the power wasted. This is also why it is critical to use the Wakelock.acquice () method with timeout parameters.
But just setting the timeout is not enough to solve the problem, such as setting how long the timeout is appropriate? When to retry and so on? To solve the above problem, the correct way may be to use a non-precision timer. Normally, we set a time to do something, but it might be better to change the time dynamically. For example, if you have another program that needs to wake up 5 minutes later than the time you set, it's best to wait until that time when the two task bundles work together simultaneously, which is how the non-precision timer works at its core. We can customize the scheduled tasks, but if the system detects a better time, it can postpone your task to save power consumption.
This is exactly what the Jobscheduler API does. It combines the ideal wake-up time based on the current situation and task, such as when you are charging or connecting to WiFi, or when the task is centralized. We can implement many free scheduling algorithms through this API.

Battery Historian

Battery Historian is the new API introduced by Android 5.0. You can get the power consumption information on your device by following the instructions below:

$ adb shell dumpsys batterystats > xxx.txt  com.package.name > xxx.txt //得到指定app相关的电量消耗信息

After getting the raw power consumption data, we need to translate the data into a more readable HTML file through a Python script written by Google:

$ python historian.py xxx.txt > xxx.html

Open this converted HTML file, you can see similar to the TraceView generated list data, where the information is very large, here is not expanded.

Because the time relationship first written here, to be continued ...

Android Performance Optimization strategy

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.