Android memory optimization

Keywords: Android Google xml Database

In the actual development of Android, there may be situations where objects that are no longer used can not be recycled by the system, which may lead to memory leaks, or even memory overflow, leading to program crash.

Detection method: LeakCanary

Optimizing scheme:

1. Check how much memory is used
The heap memory size of each APP has a hard limit. If your APP has reached the heap memory limit and tries to allocate more memory, the system will throw OutOfMemoryError. To avoid OOM, you can query how much heap space the current device has. By calling the system getMemoryInfo() query, you can return an ActivityManager.MemoryInfo object, which provides the status information of the device's current memory, including available memory, total memory, and memory below this threshold.

private void getMemoryInfo() {
    ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    activityManager.getMemoryInfo(memoryInfo);
    LogUtil.d("totalMem=" + memoryInfo.totalMem + ",availMem=" + memoryInfo.availMem);
    if (!memoryInfo.lowMemory) {
        // Running in a low memory environment
    }
}

2. Release memory when the interface is invisible
Implement onTrimMemory () in Component Callbacks 2 API. When the callback parameter level is TRIM_MEMORY_UI_HIDDEN, the user clicks the Home key or the Back key to exit the application. All UI interfaces are hidden. At this time, some unnecessary resources should be released when they are not visible.

public class MainActivity extends AppCompatActivity
    implements ComponentCallbacks2 {
    // Other activity code ...
    /**
     * Release memory when the UI becomes hidden or when system resources become low.
     * @param level the memory-related event that was raised.
     */
    public void onTrimMemory(int level) {
        // Determine which lifecycle or system event was raised.
        switch (level) {
            case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
                /*
                   Release any UI objects that currently hold memory.
                   The user interface has moved to the background.
                */
                break;
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
                /*
                   Release any memory that your app doesn't need to run.
                   The device is running low on memory while the app is running.
                   The event raised indicates the severity of the memory-related event.
                   If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will
                   begin killing background processes.
                */
                break;
            case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                /*
                   Release as much memory as the process can.
                   The app is on the LRU list and the system is running low on memory.
                   The event raised indicates where the app sits within the LRU list.
                   If the event is TRIM_MEMORY_COMPLETE, the process will be one of
                   the first to be terminated.
                */
                break;
            default:
                /*
                  Release any non-critical data structures.
                  The app received an unrecognized memory level value
                  from the system. Treat this as a generic low-memory message.
                */
                break;
        }
    }
}

The onTrimMemory() callback is added on board Android 4.0 (API level 14). For earlier versions, you can use onLowMemory() callbacks as callbacks for older versions, which are roughly equivalent to TRIM_MEMORY_COMPLETE events.

3. Careful use of services
One of the worst memory management errors is running without APP. When APP is in the background, we should stop the service unless it needs to run the task. We can use Job Scheduler as an alternative implementation. Job Scheduler places some tasks that are not particularly urgent in batches at a more appropriate time. If you have to use a service, the best way is to use IntentService to limit service life. When all requests are processed, IntentService automatically stops.

4. Use optimized data containers
Considering the use of optimized data containers such as SparseArray/SparseBooleanArray/LongSparseArray instead of traditional data structures such as HashMap, the implementation of a generic HashMap can be said to be fairly inefficient in memory because it requires mapping a separate entry object for each.

5. Avoid using enumerations on Android

6. Serialize data using nano protobufs
Protocol buffers is a language-neutral, platform-neutral, extensible mechanism for Google to serialize structured data, similar to XML design, but smaller, faster and simpler. If you need to serialize and protocol your data, nano protobufs is recommended.

7. Avoid memory loss

8. Use ProGuard to eliminate unwanted code
Use ProGuard to eliminate unwanted code, remove any redundant, unnecessary, or bloated components, resources or libraries to improve the memory consumption of APP.

9. Reduce the volume of apk
You can significantly reduce the memory usage of APP by reducing the overall size of APP. Article: Android APK Slimming Practice

10. Optimizing Layout Level
Improve performance by optimizing the view hierarchy to reduce the number of overlapping UI objects. Article: Android Rendering Optimization

11. Using Dagger 2 dependency injection
Dependency injection frameworks can simplify the code you write and provide an adaptive environment for testing and other configuration changes. If you intend to use a dependency injection framework in your APP, consider using Dagger 2, which does not use reflective scanning of APP code. Dagger is static, meaning that it does not need to run Android applications or use memory at compile time.

12. Be careful with external libraries

13. Avoid Bitmap waste
Bitmap is a major memory consumer and should be reclaimed in time when used. In addition, configuration:
inSampleSize: Scale the scale and load the image on demand to avoid unnecessary large image loading.
decode format: decode format, choose ARGB_8888/RBG_565/ARGB_4444/ALPHA_8, there are great differences.

14.Cursor Closed
If the operation of querying database is used in Cursor, the Cursor object should also be closed in time.

15. Logout of listeners
There are many listeners in Android programs that need registers and unregister s, and listeners that need to be manually add ed, so you need to remember to remove this listener in time.

Posted by bluemonster on Mon, 08 Jul 2019 13:36:23 -0700