常見的內存泄漏原因及解決方法


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();

    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM