1. 程式人生 > >記憶體洩漏優化---靜態變數導致記憶體洩漏

記憶體洩漏優化---靜態變數導致記憶體洩漏

1、要不怎麼說static關鍵字要慎用呢?來看看下面這段程式碼,Context物件為靜態的,那麼Activity就無法正常銷燬,會常駐記憶體。

public class MainActivity extends Activity{
	public static Context mContext;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mContext = this;
	}
}

解決辦法:1使用Application的Context。 2慎用statistic關鍵字

2、單例模式導致記憶體的洩漏

靜態變數導致的記憶體洩漏太過明顯,而單例模式帶來的記憶體的洩漏容易被忽略。

public class MyDBHelper extends SQLiteOpenHelper {
    public static final String DB_NAME = "mydb.db";
    public static final int DATABASE_VERSION = 1;
    public static MyDBHelper instance = null;
    private static final Object mMutex = new Object();

    private static final String DB_TABLE_STUDENT = "students";
    private static final String DB_TABLE_TEACHER = "teacher";

    private String studentTableSql = "CREATE TABLE IF NOT EXISTS students (id integer primary key autoincrement,name varchar(10),age varchar(10),sex varcher(10))";
    private String teacherTableSql = "CREATE TABLE IF NOT EXISTS teacher (id integer primary key autoincrement,name varchar(10),age varchar(10))";

    /**
     * 功能描述:單例模式建立MyDBHelper例項
     *
     * @param context
     * @return
     */
    public static MyDBHelper getInstance(Context context) {
        if (instance == null) {
            synchronized (mMutex) {
                if (instance == null) {
                    instance = new MyDBHelper(context);
                }
            }
        }
        return instance;
    }


    public MyDBHelper(Context context) {
        super(context, DB_NAME, null, DATABASE_VERSION);
    }

    /**
     * 方法描述: 構造方法
     *
     * @param context 上下文
     * @param name    資料庫名稱
     * @param factory
     * @param version
     */
    public MyDBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    /**
     * 方法描述:建立資料庫
     *
     * @param db
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(studentTableSql);
        db.execSQL(teacherTableSql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}
我們在使用的時候經常會犯一些錯誤:
/**
 * Created by lizhenya.
 */
public class HomeActivity extends Activity {
    Button btn_home;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.layout_home);
        MyDBHelper().getInstances(this);
    }
}
    單例模式的特點就是它的生命週期和Application一樣,那麼如果某個Activity例項被一個單例所持有,也就是說在單例裡面引用了它,那麼就會造成Activity物件無法正常回收釋放。所以我們儘量的使用Application的全域性Context。

3,屬性動畫導致的記憶體洩漏

    從Android3.0開始,Google提供了屬性動畫,屬性動畫中有一類無限迴圈的動畫,如果在Activity中播放此類動畫並且在onDestroy()方法中沒有停止該動畫,那麼動畫會一直迴圈下去,儘管在介面上已經無法看不到動畫了,但這個時候Activity的View會被動畫持有,而View又持有Activity,最終Activity無法釋放。下面的動畫是無限迴圈的,會洩露當前的Activity。

/**
 * Created by lizhenya.
 */
public class HomeActivity extends Activity {
    Button btn_home;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.layout_home);
        btn_home = (Button) findViewById(R.id.btn_home);
        ObjectAnimator animator = ObjectAnimator.ofFloat(btn_home, "ratation", 0, 360).setDuration(2000);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.start();
    }
}

解決方案:

    在當前Activity的onDestroy()方法中取消動畫:animator.cancel()。

/**
 * Created by lizhenya.
 */
public class HomeActivity extends Activity {
    private Button btn_home;
    private ObjectAnimator animator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.layout_home);
        btn_home = (Button) findViewById(R.id.btn_home);

        animator = ObjectAnimator.ofFloat(btn_home, "ratation", 0, 360).setDuration(2000);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        animator.cancel();
    }
}