Android memory, Android memory
I haven't written it for a long time. I don't forget it, I'm not lazy, because I am confused ~~ I don't know what to learn, what to write, what to do, and what to do. I am stupid, I don't know how to tell others what I will, and I am willing to share it with others. So I will write it out. No matter what is right or wrong, I hope everyone can take the best of it to get rid of it, do not mislead you because of me. No more nonsense ~~
Is your application memory leaked?
Check whether there is a memory leak. First, we need to see the memory information. How can we see the memory information? Here we will introduce a method. Open the Eclipse connection phone, go to DDMS, select the application to be analyzed, and click Update Heap, which is the 1 icon in, click the 1 icon and the 2 icon appears in the application process to be analyzed. The memory information of the application is displayed at the 4 position.
How can I know there is a memory leak when I see the memory information? As we can see the size of the memory applied by the analysis application, that is, the value at the 3-position, we can determine whether there is a memory leak based on the change in this value. How can we determine it? For example, if we want to determine whether there is a memory leak on the first page of the analysis application, we can do this. First exit the application, and then click Cause GC. When the three-position value is stable, record it, and then go to the application. Wait until the first interface is loaded, exit the application, and click Cause GC. Wait until the value at the third position is stable, and record it. After repeated operations, let's take a look at the value we recorded. If it shows a growth trend, there is a memory leakage problem in the first interface of the application. If it shows a horizontal trend, there is no memory leakage problem.
Where is the memory leakage?
To know where the memory leaks, you need to install a tool named MAT. If you want to install it, go to Baidu. Similarly, go to the Eclipse connection phone, go to DDMS, select the application to be analyzed, and then click A, that is, Dump HPROF file.
Wait for a moment and the following window will pop up:
Select Leak Suspects Report and click Finish. The following window appears.
Click the icon indicated by A to display the icon indicated by B. Then select Groupby class loader in B to view the applied object information of the application to be analyzed. Objects is the position of C, it is the number of applied objects. Shallow Heap is the memory size occupied by the object, and Retained Heap is the sum of the object itself and the Shallow Heap of the directly or indirectly referenced object, that is, after the object is GC, it can be recycled to the total memory. How can we determine the memory leakage from these values? The example above shows that we enter the first interface, that is, the first Activity. We know that the resources occupied by the Activity will be released when the Activity exits, therefore, the number of Objects is irrelevant to the number of times you start the Activity. Therefore, we first record the number of Objects, then enter and exit the analysis application multiple times, and then generate the hprof file. Then, we can see that the number of Objects only increases and does not decrease, this indicates that the object has memory leakage. Of course, the memory leakage of object A may be caused by the reference of object B to object A, so we need to find out whether the object is released or not, resulting in Memory leakage. The rest depends on itself. Check the increasing number of objects one by one.
How many threats does Context pose to memory?
The Context here is not the Application Context, but mainly the Activity. In the past, when I searched for how to handle memory overflow on the internet, I always said that I would release the Context, but it was still confused. Let's talk about this Context today. Then we started with the above problem. When we noticed that the number of many objects is growing and the number of these objects is equal, just as the number of objects in Zone C is 2, at this time, we should note that there is a Context that has not been released. The layout, Handler, Thread, and so on created in the Activity will save an Activity object. If one of these objects does not release the Activity, all objects in the Activity cannot be released. If a large Bitmap in the Activity is not released, the hidden danger cannot be described. I have encountered this one before. Handler was not released, so the Context was not released, while the large Bitmap in the Context was not released, as a result, the memory of the Activity increases by nearly 3 m each time, and the OOM occurs several times.
How much memory does Bitmap occupy?
First, determine how the Bitmap image size is calculated. Let's calculate the Bitmap size with a pixel depth of X to 24. We all know that Bitmap is characterized by a pixel occupying a single bit depth. For example, the bit depth is 24, that is, a pixel occupies 24b (BIT), that is, 3B.
Size (B) = width (pixel) * Height (pixel) * bit depth/8.
Size (KB) = size (B)/1024.
So the image size we mentioned above is: 500*500*24/8/1024 = kb.
What is the size of this bitmap in the Android mobile phone? We can write a code segment to test the size of other objects.
<span style="font-size:18px;"> private void testBitmapSize (Context context) { BitmapDrawable drawable = (BitmapDrawable) context.getResources().getDrawable(R.drawable.test_bitmap); Bitmap bitmap = drawable.getBitmap(); android.util.Log.d("my_test","start----------"); System.gc(); bitmap.recycle(); System.gc(); android.util.Log.d("my_test","end----------"); }</span>
We capture the log as follows:
D/my_test (14667): start ----------
D/dalvikvm (14667): GC_EXPLICIT freed 9 K, 4% free 10122 K/10503 K, paused 1 ms + 4 ms
D/dalvikvm (14667): GC_EXPLICIT freed976K, 13% free 9145 K/10503 K, paused 2 ms + 2 ms
D/my_test (14667): end ----------
Based on this, we can estimate that after the Bitmap is released, the memory size will be about 976KB, nearly 1 MB. If this is not released, it will soon overflow.
What will cause the Context not to be released?
The Context encountered by the monks is not released. This is the case. There is a rolling title in the application, which will be rolled once every time, so I will write it like this:
It is easy to see from the code that each 5 s Handler sends a message to itself, and this Handler is not released when the activity is destroyed, therefore, the Context of the View is not released, while Bitmap with more than 2 MB in the Context is not released. As a result, each time you enter the application, there will be an additional Context object, resulting in nearly 3 MB of space.
Does Bitmap need to be released?
As mentioned above, the Bitmap is not released because the Context is not released. If the Context is released, will Bitmap be released? The answer is yes. When I encountered the above Memory leakage, I still did not find the real cause: I sent a 2 m Bitmap which was not released, so I took the initiative to release it when I used up:
<p align="left"><span style="font-size:18px;"><strong><span style="color:#7F0055;">if</span></strong> (bitmap != <strong><span style="color:#7F0055;">null</span></strong> && !bitmap.isRecycled()) {</span></p><p align="left"><span style="font-size:18px;"> bitmap.recycle();</span></p><p align="left"><span style="font-size:18px;"> bitmap = <strong><span style="color:#7F0055;">null</span></strong>;</span></p><p><span style="font-size:18px;">}</span></p>
After the release, I entered the application every time, but it was indeed more than 2 m less, but there was nearly 1 m space not released. I was wondering, so I used the mat tool to see it, we found that the Context generated by the first Activity was not released, and then we found the Handler message, so we took the initiative to release the Handler message before the Activity was destroyed:
<span style="font-size:18px;"> public void releaseRes () { mContext = null; if (mHandler != null && mHandler.hasMessages(HANDLER_SEARCH_HOT_WORD)) mHandler.removeMessages(HANDLER_SEARCH_HOT_WORD); mHandler = null; }</span>
As a result, I went to observe the memory occupied by the application and kept it near a fixed value. This is another strange idea. If my Bitmap is not released, will it be leaked? So I will comment out the location where the Bitmap is released. I went to verify again and checked in and out the application multiple times. I found that the application was basically kept near that fixed value. So I think Bitmap will be released with the release of Context. The problem arises. Why do we need to take the initiative to release Bitmap? That's because before you exit the application, the space occupied by this Bitmap exists. Since you don't need it, it is a waste of space. In addition, if Bitmap is not released somewhere, this place will be called repeatedly, and the consequences are unimaginable. Therefore, when Bitmap is no longer used, it must be released, not necessarily, as long as you can ensure that the memory is sufficient.
Where can Bitmap be ignored for release?
The longest occurrence of this is where Bitmap is modified:
<span style="font-size:18px;"> BitmapDrawable drawable = (BitmapDrawable) this.getResources().getDrawable(R.drawable.test_bitmap); Bitmap bitmap = drawable.getBitmap(); android.util.Log.d("logTest","bitmap.getWidth()="+bitmap.getWidth()); android.util.Log.d("logTest","bitmap.getHeight()="+bitmap.getHeight()); Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, 500, 500); Bitmap newBitmap2 = Bitmap.createBitmap(bitmap, 0, 0, 400, 400); android.util.Log.d("logTest","bitmap="+bitmap); android.util.Log.d("logTest","bitmap.isRecycled()="+bitmap.isRecycled()); android.util.Log.d("logTest","newBitmap="+newBitmap); android.util.Log.d("logTest","newBitmap.isRecycled()="+newBitmap.isRecycled()); android.util.Log.d("logTest","newBitmap2="+newBitmap2); android.util.Log.d("logTest","newBitmap2.isRecycled()="+newBitmap2.isRecycled());</span>
Log output is like this:
D/logTest (27782): bitmap. getWidth () = 500
D/logTest (27782): bitmap. getHeight () = 500
D/logTest (27782): bitmap = android. graphics. Bitmap @ 4143c758
D/logTest (27782): bitmap. isRecycled () = false
D/logTest (27782): newBitmap = android. graphics. Bitmap @ 4143c758
D/logTest (27782): newBitmap. isRecycled () = false
D/logTest (27782): newBitmap2 = android. graphics. Bitmap @ 4143a110
D/logTest (27782): newBitmap2.isRecycled () = false
Obviously, when we modify an image, if the Bitmap to be uploaded is the same as the Bitmap to be output, the original image and the same address will be returned. If the image has different specifications, A new Bitmap is created, and the original Bitmap is not released. In this case, problems may occur. We will forget to release the original Bitmap. If multiple images are modified, the memory leakage will be serious. For example, if there are images in the Listview, we will process the image before setting it. If we forget to release the image before modification, the consequences will be unimaginable.
<span style="font-size:18px;"> if (newBitmap != null && !newBitmap.isRecycled() && newBitmap != bitmap) {newBitmap.recycle(); newBitmap = null; }</span>
Just a few lines of code can save your memory.
Can images in the layout be released to save memory?
There are methods on the Internet to release images that are not needed in the layout:
<Span style = "font-size: 18px;"> // set BitmapDrawable drawable = (BitmapDrawable) this. getResources (). getDrawable (R. drawable. test_bitmap); mImageView. setBackgroundDrawable (drawable); // release the image BitmapDrawable drawableRel = (BitmapDrawable) mImageView. getBackground (); if (drawableRel! = Null) {System. gc (); size = Runtime. getRuntime (). totalMemory (); drawableRel. setCallback (null); drawableRel. getBitmap (). recycle (); drawableRel = null; System. gc (); android. util. log. d ("test_my_log", "rel_size =" + (Runtime. getRuntime (). totalMemory ()-size);} </span>
Log is like this:
D/test_my_log (29891): rel_size = 0
D/test_my_log (29891): rel_size = 0
D/test_my_log (30292): rel_size = 0
D/test_my_log (30292): rel_size = 0
D/test_my_log (30292): rel_size = 0
The size of the released memory is 0, which indicates what it means.
Today, I will talk about this first. I will have the opportunity to talk about it again later. I would like to give my friends a pleasant meal and give them a reference to the future. I am right and wrong, just don't make fun of others ~