简体   繁体   中英

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;
    }
}

Here in this approach whenver my application exits then I can release memory by calling releaseMemory() so that myActivity instance will not be leaked.

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;
    }
}

In this approach as MyClass instance is final I can't make it null instead I can make individual variables as null.

So is My understanding correct or am I missing anything respective to memory leaks?

First question, why do you need to keep a reference on an Activity object ?

For most usage you just need a Context object. So if you want to avoid leaking your Activity take the habit to do the following by replacing :

private MyActivity myActivity;

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

with:

private Context myContext;

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

Since Activity is an implementation of Context, your code should keep working. The method getApplicationContext() will always return an Application Context which you can leak all you want.

Now if an Application Context is not enough and you really need an Activity object (if you need to start other Activity without creating a new task for exemple), first ask yourself why you can't do that in your Activity class directly. If you can't, then maybe you have taken bad decision regarding your code architecture.

If you really need to store Activity object in other object (singleton or not), please remember that activities have a lifecycle, and you need your Activity to notify your MyClass that it will be no longer available (if you don't, and you forget to call releaseMemory(), then your Activity will leak when it goes to background) :

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;
    }
}

In case your MyClass is also a Fragment , you can do the job of setting and releasing your Activity in the methods onAttach() and onDetach() (those methods are automaticaly called by Android, so you don't need to try to call them in your Activity ).

Finally, I would advise against your first code sample, because even if you call your method releaseMemory() and ensure you have no reference left in your object A , there is nothing you can do to ensure an object B doesn't still have a reference to your class MyClass .

final field can't be modified. that's why final modifier exists.

second version of your singleton is better regarding conccurency. but it will be never gc'ed until you close the app.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM