簡體   English   中英

Singleton與靜態最終實例之間的內存分配差異

[英]Memory allocation difference between Singleton vs static final instance

public class MyClass {
    private static MyClass instance = null;
    private MyActivity myActivity;
    private Button button;

    public static MyClass getInstance(){
        if (instance == null){
            instance = new MyClass();
        }
        return instance;
    }

    private MyClass(){};

    public void initialize(MyActivity activity){
        myActivity = activity;
    }

    public void releaseMemory(){
        instance = null;
    }
}

在這種方法中,只要我的應用程序退出,我就可以通過調用releaseMemory()釋放內存,從而不會泄漏myActivity實例。

public class MyClass {
    private static final MyClass instance = new MyClass();
    private MyActivity myActivity;
    private Button button;


    private MyClass(){};

    public void initialize(MyActivity activity){
        myActivity = activity;
    }

    public void releaseMemory(){
        instance = null; //Can't make it null
        //Can do for individual variables
        myActivity = null;
        button = null;
    }
}

在這種方法中,由於MyClass實例是最終的,因此我不能將其設置為null,而可以將單個變量設置為null。

那么我的理解是正確的還是我缺少與內存泄漏有關的任何內容?

第一個問題,為什么需要在Activity對象上保留引用?

對於大多數用法,您只需要一個Context對象。 因此,如果您想避免泄漏您的Activity請養成以下習慣:

private MyActivity myActivity;

public void initialize(MyActivity activity){
    myAcitivity = activity;
}

與:

private Context myContext;

public void initialize(Context context){
    myContext = context.getApplicationContext();
}

由於Activity是Context的實現,因此您的代碼應保持正常運行。 方法getApplicationContext()將始終返回一個應用程序上下文,您可以泄漏所有想要的內容。

現在,如果應用程序上下文還不夠,並且您確實需要一個Activity對象(如果您需要啟動其他Activity而不創建示例新任務),請首先問問自己為什么不能直接在Activity類中做到這一點。 如果不能,則可能是您在代碼體系結構方面做出了錯誤的決定。

如果您確實需要將Activity對象存儲在其他對象(無論是否為單個)中,請記住,活動具有生命周期,並且您需要Activity來通知MyClass它不再可用(如果您沒有,並且忘記調用releaseMemory(),那么您的Activity進入后台時將泄漏):

public class MyActivity {

    MyClass myClass; // instance initialize somewhere in your code

    onPause() {
        myClass.setActivity(this);
    }

    onResume() {
        myClass.setActivity(null);
    }
}

public class MyClass {

    @Nullable Activity myActivity; // tha @Nullable annotation helps you remember to do null checks before using this field.

    public void setActivity(Activity activity) {
        myActivity = activity;
    }
}

如果您的MyClass也是Fragment ,則可以在onAttach()onDetach()方法中設置和釋放Activity (這些方法由Android自動調用,因此您無需嘗試調用它們)在您的Activity )。

最后,我建議不要使用第一個代碼示例,因為即使調用方法releaseMemory()並確保對象A沒有剩余引用,也無法采取任何措施來確保對象B仍然沒有對象A引用您的類MyClass

最終字段無法修改。 這就是存在final修飾符的原因。

您的單例的第二個版本在一致性方面更好。 但除非您關閉應用程序,否則它將永遠不會被gc'ed。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM