一、匿名內部類持有外部類的引用,如常用的Thread、Handler和AsyncTask
如下:
public class SyncTaskDemoActivity extends Activity {
private int today = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 異步執行任務
new AsyncTask<Object, Void, Boolean>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(Object... params) {
// do something in backfround
// 長時間的耗時
while (true) {
today++;
if (today > 100000)
break;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (result) {
// success do something
} else {
// error
}
}
}.execute();
}
} ```
修改后:
public class SyncTaskDemoActivity extends Activity {
private int today = 0;
private AsyncTask mAsyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAsyncTask = new AsyncTask<Object, Void, Boolean>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(Object... params) {
// do something in backfround
// 長時間的耗時
while (true) {
if (cancel(true))
break;
today++;
if (today > 100000)
break;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (result) {
// success do something
} else {
// error
}
}
@Override
protected void onCancelled() {
super.onCancelled();
}
};
// 異步執行任務
mAsyncTask.execute();
}
@Override
protected void onDestroy() {
super.onDestroy();
mAsyncTask.cancel(true);
}
}
解決辦法:繼承該類,并聲明為靜態私有,因為靜態私有類不持有外部類的引用,對于AsyncTask可以執行cancle方法
二、靜態變量持有該類的實例,銷毀時,無法釋放該實例
以下代碼均會導致內存泄漏
public class MainActivity extends Activity{
private static Context sContext;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sContext = this;
}
}
或
public class MainActivity extends Activity{
private static View view;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = new View(this);
}
}
三、單例模式導致的內存泄漏
public class TestManager{
private List<OnDataArrivedListener> listeners = new ArrayList<>();
private static class SingletonHolder{
public static final TestManager instance = new TestManager();
}
private TestManager(){
}
public static TestManager getInstance(){
return SingletonHolder.instance;
}
public synchronized void registerListener(OnDataArrivedListener listener){
if (!listeners.equals(listener))
listeners.add(listener);
}
public synchronized void unregisterListener(OnDataArrivedListener listener){
if (listeners.equals(listener))
listeners.remove(listener);
}
public interface OnDataArrivedListener{
public void onDataArrived(Object data);
}
}
原因:由于疏忽,忘了寫解綁,就會導致內存泄漏
四、屬性動畫
屬性動畫持有該類的一個View,若該類銷毀時,屬性動畫還在執行,將導致內存泄漏
解決辦法:調用屬性動畫的cancel