Android Memory leakage optimization summary, android Leakage
Android Memory leakage optimization summary blog category: android
Android memory overflow OutOfMemoryError.
The memory allocated to applications by android phones is usually about 8 Mb. If the memory is improperly processed, it may easily cause OutOfMemoryError. The most common error in our products is the OutOfMemoryError exception,
When solving this exception, I found many reasons for OutOfMemoryError on the Internet.
OutOfMemoryError is mainly caused by the following situations:
1. The database cursor is not closed.
When operating the Sqlite database, Cursor is the set of each row in the database table. Cursor provides many methods to easily read the values in the database,
You can obtain database values based on indexes, column names, and so on. You can use a cursor to call moveToNext () to move it to the next row.
After operating the database, remember to call close () of the Cursor object to close the Cursor and release resources.
2. the cache contentview is not used to construct the adapter.
When inheriting the BaseAdapter, The getView (int position, View convertView, ViewGroup parent) method will be rewritten,
The second parameter convertView is the reusable object we will use.
Java code
1. @ Override
2. public View getView (int position, View convertView, ViewGroup parent ){
3. ViewHolder vHolder = null;
4. // If the convertView object is empty, a new object is created and reused if the object is not empty.
5. if (convertView = null ){
6. convertView = inflater. inflate (..., null );
7. // create a ViewHodler object
8. vHolder = new ViewHolder ();
9. vHolder. img = (ImageView) convertView. findViewById (...);
10. vHolder. TV = (TextView) convertView
11. findViewById (...);
12. // save ViewHodler to the Tag
13. convertView. setTag (vHolder );
14.} else {
15. // when convertView is not empty, get the View through getTag ()
16. vHolder = (ViewHolder) convertView. getTag ();
17 .}
18. // assign a value to the object and modify the displayed value.
19. vHolder. img. setImageBitmap (...);
20. vHolder. TV. setText (...);
21. return convertView;
22 .}
23. // wrap the displayed View into a class
24. static class ViewHolder {
25. TextView TV;
26. ImageView img;
27 .}
@ Override
Public View getView (int position, View convertView, ViewGroup parent ){
ViewHolder vHolder = null;
// If the convertView object is null, a new object is created and reused if the object is not empty.
If (convertView = null ){
ConvertView = inflater. inflate (..., null );
// Create a ViewHodler object
VHolder = new ViewHolder ();
VHolder. img = (ImageView) convertView. findViewById (...);
VHolder. TV = (TextView) convertView
. FindViewById (...);
// Save ViewHodler to the Tag
ConvertView. setTag (vHolder );
} Else {
// When convertView is not empty, get the View through getTag ()
VHolder = (ViewHolder) convertView. getTag ();
}
// Assign a value to the object and modify the displayed Value
VHolder. img. setImageBitmap (...);
VHolder. TV. setText (...);
Return convertView;
}
// Wrap the displayed View into a class
Static class ViewHolder {
TextView TV;
ImageView img;
}
Here we will only talk about how to use it. For more information about performance testing, see:
Principle of getView in ListView + how to place multiple items in ListView
Http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html
ListView Adapter Optimization for Android Development
Http://shinfocom.iteye.com/blog/1231511
3. unregisterReceiver () is not called after registerReceiver () is called ().
BroadcastReceiver is often used in applications. You can send broadcast notifications to UI updates after a multi-threaded task is completed, or you can receive system broadcasts to implement some functions.
You can register by code:
IntentFilter postFilter = new IntentFilter ();
PostFilter. addAction (getPackageName () + ". background. job ");
This. registerReceiver (receiver, postFilter );
When the registerReceiver () method is used in the Activity to register BroadcastReceiver, you must call the unregisterReceiver () method to cancel registration within the Activity lifecycle.
That is to say, the registerReceiver () and unregisterReceiver () methods must be paired. Generally, We can override the onDestory () method of the Activity:
Java code
1. @ Override
2. protected void onDestroy (){
3. this. unregisterReceiver (receiver );
4. super. onDestroy ();
5 .}
@ Override
Protected void onDestroy (){
This. unregisterReceiver (receiver );
Super. onDestroy ();
}
4. InputStream/OutputStream is not disabled.
This is not much to say. We need to close the input and output streams after the operation.
5. recycle () is not called after Bitmap is used ().
Poor image processing is another top cause of memory overflow (also reflected in our products ),
After processing the image, we can call the recycle () method to reclaim the image object.
Java code
1. if (! Bitmap. isRecycled ())
2 .{
3. bitmap. recycle ()
4 .}
If (! Bitmap. isRecycled ())
{
Bitmap. recycle ()
}
In addition:
Using ImageView directly shows that bitmap occupies a large amount of resources, especially when the image size is large, it may cause a crash.
Use BitmapFactory. Options to set inSampleSize, which can reduce requirements on system resources.
The property value inSampleSize indicates that the thumbnail size is one of several points of the original image size. If the value is 2, the width and height of the thumbnail are 1/2 of the original image, the image size is 1/4 of the original size.
BitmapFactory. Options bitmapFactoryOptions = new BitmapFactory. Options ();
BitmapFactoryOptions. inJustDecodeBounds = true;
BitmapFactoryOptions. inSampleSize = 2;
// Here we must set it back to false, because we set it to true before.
// After inJustDecodeBounds is set to true, decodeFile does not allocate space. That is, Bitmap decoded by BitmapFactory is Null, but the length and width of the original image can be calculated.
Options. inJustDecodeBounds = false;
Bitmap bmp = BitmapFactory. decodeFile (sourceBitmap, options );
6. Context leakage.
This is an obscure OutOfMemoryError. Let's take a look at an example provided on the Android Official Website:
Java code
1. private static Drawable sBackground;
2. @ Override
3. protected void onCreate (Bundle state ){
4. super. onCreate (state );
5.
6. TextView label = new TextView (this );
7. label. setText ("Leaks are bad ");
8.
9. if (sBackground = null ){
10. sBackground = getDrawable (R. drawable. large_bitmap );
11 .}
12. label. setBackgroundDrawable (sBackground );
13.
14. setContentView (label );
15 .}
Private static Drawable sBackground;
@ Override
Protected void onCreate (Bundle state ){
Super. onCreate (state );
TextView label = new TextView (this );
Label. setText ("Leaks are bad ");
If (sBackground = null ){
SBackground = getDrawable (R. drawable. large_bitmap );
}
Label. setBackgroundDrawable (sBackground );
SetContentView (label );
}
This code is very efficient, but it is also extremely incorrect;
During the first screen direction switch, the Activity created at the beginning was leaked. When a Drawable is attached to a View,
View sets it as a callback to Drawable. The preceding code snippet means that Drawable has a reference to TextView,
TextView has the reference of Activity (Context type). In other words, Drawable has more object references. Even if the Activity is destroyed, the memory will not be released.
In addition, the reference to Context exceeds its own lifecycle, which may also cause Context leakage. Therefore, use the Context type of Application as much as possible.
This Context has the same long life cycle as the application and does not depend on the Activity life cycle. If you want to save a long object,
And it requires a Context. Remember to use the Application object. You can easily obtain the Application object by calling Context. getApplicationContext () or Activity. getApplication.
Recently, Context leakage occurs, that is, when the Activity is destroyed, other threads are not stopped.
To sum up the problems that should be paid attention to in avoiding Context leakage:
1. Use the Context type of Application.
2. Note that the reference to Context should not exceed its own lifecycle.
3. Use the "static" keyword with caution.
4. If there is a thread in the Context, it must be stopped in onDestroy () in time.
7. static keywords
When a member variable of a class is declared static, it belongs to the class rather than the object. If we declare a large resource object (such as Bitmap and context) as static, these resources will not be recycled with the collection of objects,
So be careful when defining member variables using the static keyword.