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