首頁  >  問答  >  主體

android - 为什么定义一个static ImageView会导致内存泄露?

提示说:不要把「Do not place android context classes in static fields, this is a memory leak.」

我知道activity context 不应该被放到static fields里面因为它在app生命周期内一直存在,而且如果它通过构造函数传递给其他class的话,其他class也会一直不被回收。

但为什么ImageView不能是static(我发现SwipeRefreshLayout也不行)?是因为ImageView包含contextButtonTextView之类的view就没有这种问题。

PHPzPHPz2765 天前728

全部回覆(7)我來回復

  • 迷茫

    迷茫2017-04-18 09:08:00

    在Activity中填充佈局,可以透過如下方式:

    1.view view = View.inflate(context, R.layout.test,null );
    2.View view = LayoutInflater.from(context).inflate(R.layout.test,null);
    

    可以發現,無論哪種方式,填充後的View都是持有context的引用的,也就是Activity的引用.
    如果此時填充的view是static修飾,那麼靜態的對象將持續持有Activity的引用,導致Activity無法銷毀,Activity中所有的控件也都將無法徹底銷毀和回收.最終造成內存洩露.

    PS:為什麼要使用靜態View的方式?有什麼特殊的業務需求?

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-18 09:08:00

    static變數在記憶體中是單獨存在於記憶體區塊中的,控制項(你的問題中指的是ImageView)是持有Activity的引用的,這種情況下,Activity是沒法被徹底銷毀的,因為在記憶體中一直有一個引用(指標理解),導致Activity也無法被回收,自然就會記憶體洩漏了!
    建議,在Android中不要使用static修飾控制項!

    回覆
    0
  • 阿神

    阿神2017-04-18 09:08:00

    View需要持有Context (否則無法實現 setXXX(int resid)類別的功能)

    我也不知道Button/TextView為什麼不警告

    回覆
    0
  • 怪我咯

    怪我咯2017-04-18 09:08:00

    static變數無法被自動回收啊
    你將某個view設為靜態量,而view又持有activity的引用,這下連activity也洩露了

    回覆
    0
  • 迷茫

    迷茫2017-04-18 09:08:00

    IPC說: static對於Android四大組件來說, 簡直就是大殺器

    回覆
    0
  • 阿神

    阿神2017-04-18 09:08:00

    因為static的生命週期很長比目前activity長

    回覆
    0
  • 怪我咯

    怪我咯2017-04-18 09:08:00

    這麼說吧,這是java基礎.靜態變數在類別文件編譯成字節碼後,載入方法區的時候,就會初始化靜態變數,而且靜態變數會一直存在,而沒有static修飾的activity,會在new的時候,在堆中申請空間,當activity沒用的時候,gc會按照gc-root遍歷此activity有沒有被引用,由於activity的context被持有,ImageView view = LayoutInflater.from(context).inflate(R.layout.test,null);,所以,gc不能回收,造成內存洩漏,,當直到虛擬機器結束進程(也就是app停止),

    回覆
    0
  • 取消回覆