關於匿名內部類,非靜態內部類會造成記憶體洩露的隱患。
注意是記憶體洩露,不是記憶體溢位。啊
首先先看一下下面這樣一段程式碼
@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable()
{
@Override
public
void run() {
while (true)
{
SystemClock.sleep(1000);
}
}
}).start()
}
Thread 是一個匿名內部類,,當我們finish的時候,該activity例項不會真正銷燬,GC機制也不會進行該例項的垃圾回收,因為匿名內部類和非靜態內部類持有外部類的強引用,也就是說Thread持有外部activity的強引用,而thread內部while(true)是死迴圈,執行緒不會停止,對外部activity的強引用也不會消失。這樣就造成了
memory leak,記憶體溢位。通常情況下我們可以設定一個flag,在activity,的生命週期ondestroy中改變flag的狀態,但是!!!主執行緒和子執行緒的執行時有執行緒排程的,也就是說會造成競爭的現象,兩個執行緒會爭奪cup時間片的執行權,額。。越挖越深,這又會造成我們雖然改變的flag的狀態,但是,子執行緒中的flag並不是馬上就能改變值,因為jvm memory model,原型和執行原理,所有的執行緒都是在自己的工作記憶體中工作的,對值得操作是先從主記憶體讀取到工作執行緒的工作記憶體中,然後cpu對工作記憶體的值進行修改,最後再寫回主記憶體,所以主執行緒對flag的操作可能恰好的發生在子執行緒已經讀完主記憶體的值到工作記憶體,但是還沒有執行的這段時間,所以,我們應該讓flag的狀態改變能夠讓子執行緒馬上可見,應該在宣告flag的時候加上
imageView.setBackground(background);很聰明,這樣無論旋轉多少次螢幕,bitmap都不會重新載入了,省去了大量的時間,但是!!!
@Override
public
void handleMessage(Message
msg) {
super.handleMessage(msg);
}
};和匿名內部執行緒thread一樣,會造成內部洩露的隱患。