Knowledge points you must understand about memory optimization

1. Basic knowledge of memory

1. Java memory life cycle:

  • 1. Creation phase ( Created) : The system creates java objects through the following steps:
    • 1. Allocate memory space for the object
    • 2. Construct objects
    • 3. Initialize the static members from the superclass to the subclass in turn, and the initialization of the class is carried out when the ClassLoader loads the class
    • 4. Superclass member variables are initialized in order, and the constructor of the superclass is called recursively
    • 5. Subclass member variables are initialized in order. Once the subclass is created, the subclass constructor calls the object and assigns values ​​to the object variables.
  • 2. Application stage ( InUse)

The object is held by at least one strong reference, unless explicitly used by soft, weak, or phantom references

  • 3. Invisible stage ( InVisible)

The invisible here is relative to the application. It is invisible to the application, but it may still exist in the memory. The most common case is the temporary variable in the method, and the program execution has exceeded its scope. , but it may still be held by static variables in the virtual machine or strong references such as jni. These strong references are the so-called "GC Root", which is also the direct cause of memory leaks

  • 4. Unreachable phase ( UnReachable)

The object is no longer held by any strong reference, and the GC finds that the object is no longer reachable

  • 5. Collection stage ( Collected)

The GC finds that the object is unreachable and the GC is ready to reallocate memory for the object. If the finalize() method has been implemented by the class, it will be executed. Here is a special note: don't overload the finazlie() method! There are two reasons: 1. It will affect the object allocation and recycling speed of the JVM 2. It may cause the object to be "resurrected" again

  • 6. Final stage ( Finalized)

After the finalize() function of the object is executed, the object is still in an unreachable state, and the object enters the finalization phase

  • 7. Memory reallocation phase ( Deallocaled)

The GC reclaims or reallocates the memory space occupied by the object, and the object disappears completely.

2. Java memory model

In order to better manage memory, JVM divides memory into several parts

java memory model-runtime data area.png

  • Method area : storage class information, constants, static variables, shared area for all threads
  • Heap area : The area with the largest memory. Objects created by all threads are allocated memory in this area, and only references to objects in the heap are allocated in the virtual machine stack. GC mainly processes this part of the area, which is also the main area where memory leaks occur, and all threads share the area.
  • Virtual machine stack : store the local variable table of the current thread, the operand stack and other data, thread exclusive area
  • Native method stack : similar to the virtual machine stack, except that this area is used for the native layer
  • Program counter : store where the current thread executes the target method.

3. Which objects are reclaimed by GC (the so-called "garbage")

Use the following two methods to determine which is garbage:

  • 1. Reference counting

Add a reference count to the object. When the object is strongly referenced in sequence, the counter is +1, and the strong reference is touched, and the counter is -1. If the counter is 0 during Gc, it means that there is no object reference, and the object is garbage and can be recycled.

reference count.pngBut this method cannot solve the situation of circular references: if A refers to B, and B refers to A, then A and B can never be recycled, resulting in memory leaks , so there is the following method

Reference Counting Circular References.png

  • 2. Root Search

Define a series of "GC Root" nodes as the initial node. The path from this node to search downwards is a reference chain. If an object is not referenced by any reference chain, it means that the object is unreachable . The object is trash, can be recycled

gcroot.png

4. Java virtual machine memory recovery algorithm:

  • 1. Mark-clean algorithm

Mark objects reachable by GC roots, and clean up unmarked objects. Objects are not moved, and are suitable for memory blocks with a high survival rate. memory fragmentation

  • 2. Marking-Collating Algorithm

First use the mark-cleanup algorithm to clear garbage, then move the memory from the back to the front, clear memory fragments, and update the pointer of the object at the same time, which will consume a certain amount of performance

  • 3. Copy-Clear Algorithm

Divide the memory block into the object area and the free area. Objects are allocated in the object area. When the object area is full, clear the garbage in the object area, then copy the uncleared objects to the free area, clear the object area, and let the object area and the free area Exchange, so that memory fragments can be cleared by copying, which is more efficient than moving objects, suitable for situations where there are fewer surviving objects, and half of the memory will be wasted

  • 4. Generational recycling strategy

The essence of the actual application of the first three algorithms is the new generation, the old generation, and the permanent generation. Most virtual machine manufacturers use this method for gc

新生代:朝生夕灭,存活时间短。eg:某一个方法的局部变量,循环内的临时变量等等。
老年代:生存时间长,但总会死亡。eg:缓存对象,数据库连接对象,单例对象等等。
永久代:几乎一直不灭。eg:String池中的对象,加载过的类信息。

5.Android memory recovery mechanism

In the advanced system version of Android, there is a Generational Heap Memory model for the Heap space:

Android memory recycling mechanism.awebp

The entire memory is divided into three areas :

  • 1. Young Generation ( 年轻热恋区,来得快去的也快) consists of one Eden area and two Survivor areas,

    • 1. Most of the new objects generated in the program are in the Eden area,
    • 2. When the Eden area is full, the surviving objects will be copied to one of the Survivor areas,
    • 3. When the Survivor area is full, the surviving objects in this area are copied to another Survivor area,
    • 4. When the Survivor area is also full, the surviving objects in it will be copied to the old generation.
  • 2. Old Generation ( 年老不动区,说我老的,都被gc了) Elderly area, older, indicating that it is not easy to be recycled

  • 3. Permanent Generation stores static classes and methods (in JDK 1.8 and later versions, the Meta-space implemented in local memory has replaced the permanent generation)

6. GC type:

  • kGcCauseForAlloc : gc caused by insufficient allocated memory, this time will trigger: stop world.

logcat log:

zygote: Alloc concurrent copying GC freed 5988(382KB) AllocSpace objects, 381(382MB) LOS objects, 59% free, 1065KB/2MB, paused 2.809ms total 87.364ms
  • kGcCauseBackground : When the memory reaches a certain threshold, background gc will be triggered, and background gc will not cause stopworld.

logcat log:

zygote: Background concurrent copying GC freed 3246(222KB) AllocSpace objects, 19(19MB) LOS objects, 1% free, 364MB/370MB, paused 19.882ms total 60.926ms
  • kGcCauseExplicit : Shows gc triggered by System.gc() when called.

logcat log:

zygote: Explicit concurrent copying GC freed 32487(1457KB) AllocSpace objects, 6(120KB) LOS objects, 39% free, 9MB/15MB, paused 796us total 40.132ms
  • kGcCauseForNativeAlloc : Triggered when the memory allocation of the native layer is insufficient

There are also some such as kGcCauseCollectorTransition , kGcCauseDisableMovingGc , etc. will not be introduced

Through the logs in logcat, you can also see a usage of the current application memory, and make some targeted optimizations

Under the Dalvik virtual machine, GC operations are all concurrent, which means that each triggering of GC will cause other threads to suspend work (including UI threads). In ART mode, unlike Dalvik, GC only has one recycling algorithm. ART will choose different recycling algorithms in different situations. For example, when Alloc memory is insufficient, non-concurrent GC will be used, but after Alloc, it is found that the memory reaches a certain threshold. Concurrent GC will be triggered again. So in ART mode, not all GCs are non-concurrent.

7. LMK mechanism

LMK 全称Low Memory Killer`, LMK is a memory recovery mechanism triggered according to the memory threshold level. When the available memory of the system is low, it will selectively kill the process strategy.

When selecting a process to kill, the system will make an assessment based on the running status of the process and weigh the "importance" of the process. The basis for the trade-off is mainly the four major components .

If memory reduction is required, the system eliminates the least important processes first, then less important processes, and so on, to reclaim system resources.

LMK.webpIn Android, the application process is divided into 5 levels (excerpted from Google documents): The importance level of APP in Android is 5 levels:

Foreground process

Visible process

Service process

Background process

Empty process

Each level of process has a corresponding process priority . The priority of each process is not fixed. For example, after a foreground process enters the background, AMS will initiate a request to update the process priority.

Before 5.0, the process priority update was directly completed by AMS calling the kernel, but after 5.0, the system started a lmkd service separately to handle the process priority issue.

Android background killing series: Principle of LowMemoryKiller

2. Commonly used memory optimization tools

1.LeakCanary

LeakCanary is a MAT-based automatic memory leak detection tool provided by Square for Android developers. It is a tool that is actually a jar package.

1. Basic usage :

  • 1. Import dependent libraries
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
  • 2. We set up a list in the app
class MyApp:Application(){
    
    
    val viewList = mutableListOf<View>()
    override fun onCreate() {
    
    
        super.onCreate()
    }

}
fun MyApp.setView(view: View){
    
    
    viewList.add(view)
}
fun MyApp.removeView(view: View){
    
    
    viewList.remove(view)
}

  • 3. Call in Activity:
onCreate{
    
    
    1.将view放入app的viewList中
    app?.setView(tv)
    2.调用:watcher监控tv
    AppWatcher.objectWatcher.expectWeaklyReachable(tv,"test main leak")
}
  • 4. After running at this time: The log appears:
D/LeakCanary: Found 1 object retained, not dumping heap yet (app is visible & < 5 threshold)

LeakCanary detects that an object has not been recycled, and the notification bar will display it. Clicking on the notification bar logcat will display the corresponding object information. We exit the application to view the log system:

D/LeakCanary: Found 5 objects retained, dumping heap now (app is invisible)

    ┬───
    │ GC Root: System class
    │
    ├─ android.provider.FontsContract class
    │    Leaking: NO (MyApp↓ is not leaking and a class is never leaking)
    │    ↓ static FontsContract.sContext
    ├─ com.allinpay.testkotlin.leakcanary.MyApp instance
    │    Leaking: NO (Application is a singleton)
    │    mBase instance of android.app.ContextImpl
    │    ↓ MyApp.viewList
    │            ~~~~~~~~
    ├─ java.util.ArrayList instance
    │    Leaking: UNKNOWN
    │    Retaining 101.2 kB in 1415 objects
    │    ↓ ArrayList[0]~~~
    ╰→ com.google.android.material.textview.MaterialTextView instance
    ​     Leaking: YES (ObjectWatcher was watching this because test main leak and View.mContext references a destroyed
    ​     activity)
    ​     Retaining 101.1 kB in 1413 objects
    ​     key = f15737ab-8866-4235-af60-7cec30a144b3
    ​     watchDurationMillis = 17861
    ​     retainedDurationMillis = 12856
    ​     View is part of a window view hierarchy
    ​     View.mAttachInfo is null (view detached)
    ​     View.mID = R.id.tv
    ​     View.mWindowAttachCount = 1
    ​     mContext instance of com.allinpay.testkotlin.MainActivity with mDestroyed = true

Where the suspected overflow can be seen:

FontsContract.sContext->MyApp.viewList->ArrayList[0]->MaterialTextView instance->activity

Of course, you can also view it directly on the device:

LeakCanary.png

Cause of the problem : MyApp.viewList holds a reference to the TextView in the activity. When the Activity exits, the TextView does not exit, and the Activity object cannot be recycled, which eventually causes memory overflow.

Solution : Clear the view in viewList when the Activity exits, as follows: We call the following code at the onDestroy of the Activity: tv?.let { app.viewList.remove(it) } After exiting the application, the notification bar is not displayed, and the logcat log Display: LeakCanary: All retained objects have been garbage collected, indicating that there is no memory overflow

Two: working principle:

  • 1. Use Provider to monitor the Activity life cycle when the application starts
  • 2. When the Activity calls onDestroy, the callback triggers the event monitoring of LeakCanary, using a ReferenceQueue for monitoring
  • 3. If the unreleased Activity instance is held in the memory, the runGc method of the custom GC processor will be called to recycle
  • 4. After recycling in 3, if there are still objects that have not been released, the dumpHeap operation will be prompted in the logcat, toast and notification bar, and the dump file will be analyzed after dumpHeap, using the shark open source library
  • 5. After the dump is successful, it will be displayed in the form of a notification, and an Intent will be mounted. When the notification is clicked, the mounted Intent will be executed and the status information of the heap will be displayed.

2.Android Studio Profiles

Android Profiler is provided by as to scan the memory usage of the device at a certain point in time, or the memory usage of a period of time. The performance and use of the new version of asp are more convenient.

How to use it ?

  • 1. Directly click the profier button on the toolbar.

asp1.png

  • 2. Select Memory in the Profiler panel

asp2.png

  • 3. At this time, the memory usage of the current device will be displayed as follows.

asp3.png

Here to explain the memory information box:

- 1.Others:系统不确定归类到哪一类的内存
- 2.Code:存储代码和资源的信息,如dex字节码,经过优化或者编译后逇dex代码,.so库和字体等
- 3.Statck:原生堆栈和 Java 堆栈使用的内存。这通常与您的应用运行多少线程有关。
- 4.Graphics:图形缓冲区队列为向屏幕显示像素(包括 GL 表面、GL 纹理等等)所使用的内存。(请注意,这是与 CPU 共享的内存,不是 GPU 专用内存。)
- 5.Native:从 CC++ 代码分配的对象的内存。
- 6.Java:从 Java 或 Kotlin 代码分配的对象的内存。
- 7.Allocated:您的应用分配的 Java/Kotlin 对象数。此数字没有计入 CC++ 中分配的对象
  • 4. First click the trash can in the asp to perform a gc, switch to the Android device and click to the next page, assuming it is page B, then switch to the asp and click the download button, which is "dump java heap" At this time, a heap dump file will be generated , this file is the memory usage of the current point device,

asp4.pngHere we look at the 5 places in the label:

Note 1: Select the heap to check

  • View all heaps : View all heap situations.
  • View app heap : The main heap where your app allocates memory.
  • View image heap : The system boot image, which contains classes preloaded during startup. The assignment here ensures that it never moves or disappears.
  • View zygote heap : copy-on-write heap, where the application process is derived from the Android system.

Callout 2: Choose how to sort

  • Arrange by class : Groups all assignments by class name. It's the default value.
  • Arrange by package : Groups all assignments by package name.
  • Arrange by callstack : Groups all allocations into their corresponding callstack.

Callout 3: Select which classes to display

  • Show all classes : Display all Class classes (including system classes), which is the default value.
  • Show activity/fragment Leaks : Show leaked activity/fragment.
  • Show project class : Show the Class class of the project.

Note 4: Here you can search for the class you are looking for. For example, if you suspect that an object has a memory leak, you can directly search for this class.

Note 5: Click here to directly display the memory leak provided by asp

Note 6: This shows the specific situation of the current device memory usage

  • Allocations : the number of class objects in the current memory
  • Native Size : The total amount of native memory used by this object type in bytes. You'll only see this column if you're using Android 7.0 and higher You'll see memory here for some objects allocated in Java because Android uses native memory for some framework classes like Bitmap.
  • Shallow Size : The memory (in bytes) occupied by this object itself.
  • Retained Size : The total memory usage (in bytes) of all objects on this object reference chain
  • Depth : the shortest number of hops from any GC root to the selected instance

How to view the reference chain of memory leaks :

Click the type of possible leak, then click "References" in the detailed list, and check "Show nearest GC root only". You can display the reference chain of the current object leak. See here because the viewList object in MyApp refers to the context in MainActivity. It is consistent with the results of the previous LeakCanary analysis.

asp5.png

How to view memory usage over time:

Click on the Memory interface, and a range will be displayed, and the developer can select the start and end time as needed.

asp difference.png

Not only the above functions, ASP can also visually observe the number and size of objects created on the method path , then this function is very powerful

asp visual.png

3.MAT

About MAT has also been mentioned above, here are two points:

  • 1. Generally, the exported heap file needs to be converted by the prof tool before it can be imported into MAT
  • 2. The comparison function of the two heap files is really powerful, which can accurately analyze the memory usage before and after the two heap files .

For the usage of MAT, please refer to this article :

Compared to traditional memory analysis tools. The power of MAT is that it can not only analyze a certain period of time, but also analyze the comparison of two heap files before and after, so as to obtain the memory usage difference between the two before and after services.

According to the previous analysis, ASP fully supports this function and replaces it, and the MAT analysis steps are complicated, and ASP can be seamlessly connected with the code. Which would you choose?

3. Common memory leak scenarios in development

Memory leaks can be simply understood as the inability of the system to reclaim useless objects. Here is a summary of several memory leak scenarios and solutions that often occur during project development.

  • 1. The resource is not released

比如

  • 1. BroadcastReceiver is not unregistered
  • 2. Cursor is not closed in time
  • 3. Various streams are not closed
  • 4. Bitmap does not call recycle for recycling
  • 5. When the Activity exits, the asynchronous tasks started by RxJava and coroutines are not canceled
  • 6.Webview

Under normal circumstances, as long as the Webview is used once in the application, the memory it occupies will not be released. Solution: We can start an independent process for WebView, use AIDL to communicate with the main process of the application, and the process where WebView is located can be According to the needs of the business, choose the right time to destroy, so as to achieve the purpose of releasing the memory normally.

  • 2. Static variables store large data objects

As previously analyzed, static variables are stored in the method area, and the method area is an area with a relatively long life cycle and is not easy to be recycled. If the data stored in static variables takes up a large amount of memory, memory leaks and OOM are prone to occur.

  • 3. Singleton

If the context of the Activity is used in the singleton, it will cause a memory leak. Solution: use the context of the Application. Or use a weak reference to wrap the context, and get it when you use it. If you can't get it, it means it has been recycled, and return the context that injects a new Activity.

  • 4. Static instance of non-static inner class

Here we first explain the difference between static inner classes and non-static inner classes:

  • 1. Static inner classes do not hold references to outer classes

    A non-static inner class holds a reference to an outer class. A non-static inner class can access all properties and methods of the outer class, even if they are private, for this reason, while a static inner class can only access static methods and properties of the outer class.

    • 2. Static inner classes do not depend on outer classes

    The non-static inner class and the outer class are parasitic, and they live and die together. The static inner class does not depend on the outer class. The outer class is recycled, but it will not be recycled. You can understand it as a new class: compiled format: outer class $ inner class. This can also be seen from the construction method:

    Non-static inner class : Inner in = new Outer().new Inner();

    Static inner class : Inner in = new Outer.Inner();

Non-static inner classes need to create an outer object to create the inner, so it is a symbiotic relationship. Symbiosis here means that when the outer class is gone, the inner class will also be gone, and conversely, if the inner class is gone, the outer class may still exist. The static inner class does not create an external object, so it is an object that exists independently. The form is like an inner class, but it is actually a new class.

Through the above analysis, it can be seen that if the static instance of the non-static inner class will always hold the reference of the outer class, if the outer class is an Activity or holds a reference to an Activity, it may cause a memory leak. This is what everyone develops need to pay special attention.

  • 5. Handler temporary memory leak

After the Message is sent, it is stored in the MessageQueue. There is a target in the Message, which is a reference to the Handler. If the Message exists in the Queue for too long, the Handler cannot be recycled. If the Handler is non-static, we said above that the non-static inner class holds a reference to the outer class, that is, a reference to the Activity or Service, which makes the Activity or Service unable to be recycled. Solution: 1. Use a static class for the Handler, and then use a weak reference to the object held by the Handler, so that even if the Handler is not released, the context object held by the Handler can also be released. 2. When the Activity exits, remember to remove Discard the message in the message queue.

  • 6. Memory leaks caused by objects in the container not being cleaned up

Before exiting the program, clear the items in the collection, then set them to null, and then exit the program

  • 7. Memory leak caused when using ListView

When constructing the Adapter, use the cached convertView.

4. How to practice memory optimization in actual projects

1. Runtime memory detection optimization

Running memory refers to a page jumping to another page, or a certain task needs to be performed in a certain business. See the memory comparison before and after the task. Here we can use two methods: Method 1: Use MAT to compare two pages The memory data at the time, find out the possible leakage point Method 2: Use ASP to specify the memory start and end, and then use "show nearest gc root" to view the memory usage

2. Static memory optimization

The static memory mentioned here refers to the part of the memory that exists along with the entire life cycle of the App, that is, the bottom layer. The specific way to obtain this part of the memory snapshot is: Open the App and start heavy use of the App, basically open every The main function of a main page, then go back to the home page, enter the developer options to open "do not keep background activities", and then return our app to the background. Finally, GC, dump memory snapshot

3. Memory leak monitoring

In addition to the basic functions of LeakCanary, memory leak detection can also customize the processing results: First, inherit DisplayLeakService to implement a custom monitoring and processing Service, the code is as follows:

public class LeakCnaryService extends DisplayLeakServcie {
    
    
    
    private final String TAG = “LeakCanaryService”;
    
    @Override
    protected void afterDefaultHandling(HeapDump heapDump, AnalysisResult result, String leakInfo) {
    
    
        ...
    }
}

Rewrite the afterDefaultHanding method, and process the required data in it. The definitions of the three parameters are as follows:

  • heapDump: Heap memory file, you can get the complete hprof file to use MAT analysis.
  • result: The monitored memory status, such as whether there is a leak, etc.
  • leakInfo: Leak trace details, in addition to memory leak objects, and device information.

Then when installing, just use the custom LeakCanaryService, the code is as follows:

public class BaseApplication extends Application {
    
    
    
    @Override
    public void onCreate() {
    
    
        super.onCreate();
        mRefWatcher = LeakCanary.install(this, LeakCanaryService.calss, AndroidExcludedRefs.createAppDefaults().build());
    }
    
    ...
    
}

After getting the memory information: we can save the data locally and upload it to the server for analysis.

5. Notes on memory usage during development

1. Use weak references

1. Weak references can be used in some cases , so that objects can be recycled in time to prevent memory leaks

2. Memory multiplexing

The full utilization of memory can help our equipment greatly reduce the probability of OOM occurrence.

So how to achieve memory reuse ?

  • 1. Resource reuse : reuse of common strings, color definitions, and simple page layouts
  • 2. View reuse : You can use ViewHolder to implement ConvertView reuse.
  • 3. Object pool : display and create an object pool, implement reuse logic, and use the same memory space for the same type of data.
  • 4. Multiplexing of Bitmap objects : Use the inBitmap attribute to tell the Bitmap decoder to try to use the existing memory area, and the newly decoded bitmap will try to use the pixel data memory area occupied by the previous bitmap in the heap.

3. Picture optimization

Several situations of image OOM problems :

  • 1. A page loads too many images
  • 2. Loading large images without compression
  • 3. The Android list loads a large number of bitmaps without using the cache

Image formats supported by Android :

  • png : Lossless compressed image format, supports transparent channels, generally takes up a lot of space
  • Jpeg : A lossy compressed image format that does not support transparent channels
  • webp : Released by Google in 2010, it supports lossless and lossy, ideal
  • gif : Multi-frame animation is supported, but Android's own image library does not support it, and a third-party framework is required

Image storage optimization method

1. 尺寸优化: Realized by reducing width and height

2. 质量压缩: Change the memory occupied by a pixel (optimize the decoding rate)

3. 内存重用: The inBitmap attribute needs to be used

Size optimization : There are two main methods that work

intJustDecodeBounds=true(可以在不加载图片的情况下获得图片的宽高)
inSampleSize(用合适的压缩比)

Size compression.webp Quality compression : using RGB-565 instead of ARGB-8888 can reduce the image memory usage

Memory reuse : InBitmap, the subsequent images must be <= the size of the first image.

memory reuse.webp

It can be implemented in combination with LruCache. When LruCache removes images that exceed the cache size, it temporarily caches the Bitamp to a soft reference set. When a new Bitamp needs to be created, it can find the most suitable Bitmap for reuse from this soft reference set and reuse it. It should be noted that the newly applied Bitmap and the old Bitmap must have the same decoding format, and before Android 4.4, only the memory area of ​​Bitamp with the same size can be reused, but after Android 4.4, any bitmap memory area can be reused .

Image loading optimization method :

  • 1. Asynchronous optimization : the picture is placed in the background request (does not occupy the resources of the main UI)
  • 2. Picture cache : cache the pictures in the list (caching in local files)
  • 3. Network request : use OkHttp for image request (many advantages)
  • 4. Lazy loading : When the picture is presented in the visible area, it will be loaded

The loading of images generally uses a multi-level cache loading process:

Image cache.webp

  • 5. Use a third-party image loading library At present, the third-party loading library is relatively mature and can be directly packaged as a basic library. Comparison of common image loading libraries at present:

Picture loading tripartite library comparison.png

4. Actively release the memory when the available memory of the App is too low

When the App retreats to the background and the memory is tight and is about to be killed, choose to rewrite the onTrimMemory/onLowMemory method to release the image cache and the static cache to protect itself.

5. Release the reference to the image when the item is recycled and invisible

ListView: Therefore, every time the item is recycled, the data will be re-bound when it is reused. You only need to release the image reference when ImageView onDetachFromWindow. RecyclerView: Because the first choice is to put it into mCacheView when it is recycled and invisible, here the item is reused and does not need to bind ViewHolder to rebind the data, only after being recycled into mRecyclePool and taken out for reuse will it be rebound Data, so rewrite the onViewRecycled() method in Recycler.Adapter to release the image reference when the item is recycled into the RecyclePool.

6. Avoid creating unnecessary objects

For example, we can use StringBuffer and StringBuilder when concatenating strings.

7. Memory optimization in custom View

For example, do not perform object creation in the onDraw method. Generally speaking, objects should be created in the constructor of the custom View.

8. Try to use static inner classes to avoid some memory leaks

Well, the above is the author's understanding of memory optimization, I hope you can gain something from it

reference

Practice App memory optimization: how to do memory analysis and optimization in an orderly manner

Memory optimization for Android performance optimization

Android memory optimization, memory leak monitoring and troubleshooting

Android Memory - Garbage Collection (GC) Mechanism

Android background killing series: Principle of LowMemoryKiller

LeakCanary official website

referenceQueue usage

Carson takes you to learn Android: Comparison of mainstream open source image loading libraries (UIL, Picasso, Glide, Fresco)

Reprint: https://juejin.cn/post/7159494369576222757

Guess you like

Origin blog.csdn.net/gqg_guan/article/details/130704325