2017-03-07 31 views
0

在我的活動中,我想要一個浮動的Action按鈕在活動加載後1秒出現。正在調用新的Runnable()內部靜態方法安全內存泄漏?

爲此,我創建了一個像這樣的新靜態方法。

public class utility { 

public static void delayedShowFab(final FloatingActionButton fab) 
    { 
     new Handler().postDelayed(new Runnable(){ 
      @Override 
      public void run() { 
       fab.show(); 
      } 
     }, 1000); 
    } 
} 

我打電話這樣的方法:

@Override  
protected void onCreate(Bundle savedInstanceState) { 
    final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
    utility.delayedShowFab(fab); 
} 

是我的代碼從內存泄漏安全嗎?新的Runnable和新的Handler對象會在1秒後自動銷燬嗎?

+0

我已經放棄了這樣的設計,他們似乎從來沒有爲我正確工作。未知的崩潰一秒鐘變成五個,因爲一些其他進程佔用CPU。今天,我將只做最後一步建立用戶界面,使按鈕可見,並繼續做出一個偉大的應用程序。 – danny117

回答

1

是和否。在正常操作中,參考值將被清除並且內存將被釋放。從技術上講,如果Activity在一秒鐘之前被殺死,則會有內存泄漏。 FloatingActionButton仍然會提及其母公司Context。所以Activity將留在內存中,直到處理程序處理消息,在這種情況下,晶圓廠將顯示,但由於活動不再可見,所以沒有任何明顯的情況發生。

這對性能沒有太大的影響,因爲它只有一秒鐘。這一秒只有一些小的開銷,但沒有什麼意義。 真實問題是,如果你延長那段時間,比如說1分鐘。

public class utility { 

public static void delayedShowFab(final FloatingActionButton fab) 
    { 
     new Handler().postDelayed(new Runnable(){ 
      @Override 
      public void run() { 
       fab.show(); 
      } 
     }, 1000 * 60); 
    } 
} 

現在,讓我們說,用戶只需決定到分鐘內一百倍旋轉手機(也許他慢跑和屏幕上。誰知道?)。

每次屏幕旋轉時,都會使用新的FAB創建新的活動。您立即發佈到主線程以等待另一分鐘。創建的每個活動都將存在,直到此消息運行。這意味着該活動中包含的所有資源在該持續時間內也將存在。

要解決這個問題,有幾個選擇。

選項1:取消操作。

保持API不變。您可以返回取消操作的方法。此類似:

public class utility { 

public interface Cancelable { 
    void cancel(); 
} 

public static void delayedShowFab(final FloatingActionButton fab) { 
     final Handler handler = new Handler(); 
     final Runnable runnable = new Runnable(){ 
      @Override 
      public void run() { 
       fab.show(); 
      } 
     }; 

     handler.postDelayed(runnable, 1000); 

     return new Cancelable() { 
      public void cancel() { 
       handler.removeCallbacks(runnable); 
      } 
     } 
    } 
} 

然後,在活動的onDestroy方法,只需調用返回的對象cancel

選項2:使用弱引用

WeakReferences用於保存到一個對象的引用,而不包括在它的引用計數。這樣,當所有對該對象的引用都消失時,它將消失。

因此,在這種情況下,您將持有對FloatingActionButon 的WeakReference,如果它仍然存在,則只能調用show

public class utility { 

public static void delayedShowFab(final FloatingActionButton fab) 
    { 
     final WeakReference<FloatingActionButton> ref = new WeakReference<>(fab); 
     new Handler().postDelayed(new Runnable(){ 
      @Override 
      public void run() { 
       FloatingActionButton fab = ref.get(); 
       // You always have to check because it may disappear. 
       if(fab != null) { 
        fab.show(); 
       } 
      } 
     }, 1000 * 60); 
    } 
} 

在這種解決方案中,RunnableWeakReference將留在存儲器中用於所述消息的持續時間,但是開銷比全活動顯著以下。

+0

非常豐富!謝謝。 – BuggyCoder