0

Let's say I have Activity1 that creates a simple custom object CustObject. CustObject doesn't reference any Context or similar type of object. Then, I want to pass this instance to Activity2 by setting it as a static variable in Activity2. Have a look at the corresponding code:

public class CustObject {

    private int attr;

    public CustObject(int arg) { // takes only integers and Strings
        attr = arg;
    }
}

Here's the first activity :

public class Activity1 extends Activity {

    private CustObject co;

    @Override
    protected void onCreate(Bundle b) {
        co = new CustObject(42);
    }

    public void launchActivity2() {
        Activity2.co = co;
        startActivity(new Intent(this, Activity2.class);
    }
}

And here's the second activity :

public class Activity2 extends Activity {

    public static CustObject co;

    @Override
    protected void onCreate(Bundle b) {
        // stuff
    }

    // Do operations on the co object.
}

So my thought is that when we launch Activity2, we only "leak" the co object - which is wanted - but the rest of Activity1 and its context can be garbage collected if necessary without any problems/leaks, right?

Note that I want to do it that way because, the CustObject co is likely to be changed by Activity2 and I would like these changes to be displayed automatically in Activity1 if it hasn't been killed. If it has been killed, then it works because everything will be reloaded and the changes to CustObject in Activity2 were also stored in a database.

Thank you for your help!

PS : Also, I've always wondered if launching an activity by giving "this" as context for an Intent is leaking the parent activity??

Louis Durand
  • 187
  • 9
  • Generally speaking, static variables arent how you share data between activities. Activity1 could be killed at any point by the OS for memory management – OneCricketeer Aug 04 '16 at 12:52
  • 3
    You're going to ***love*** process death, when Android kills your app, you return to somewhere in the middle, but all your "static" fields are cleared out! :) – EpicPandaForce Aug 04 '16 at 12:53
  • Along with that point - your Activitys overlay one another, so do you really need a changes to be rendered automatically on a screen you can't see? You can pass data between Intents from `startActivityForResult` and then `setResult`, followed by `onActivityResult` – OneCricketeer Aug 04 '16 at 12:55
  • If Activity1 gets killed, CustObject co will be cleared too? But if I hold a reference to it in Activity2 it shouldn't be cleared? – Louis Durand Aug 04 '16 at 12:57
  • @LouisDurand once set static, the object will noty be GCed, reagrdless of the Activitys state. – Vaiden Aug 04 '16 at 13:35
  • @Vaiden yeah ok that's legit for me. But only the CustObject, not Activity1's context. – Louis Durand Aug 04 '16 at 14:01
  • @EpicPandaForce yeah actually I think that there's a problem with my solution if Activity2 get's killed and then resumed.. So I will go with Intents and startActivityForResult and so on.. It's just a bit more work and less handy x) – Louis Durand Aug 04 '16 at 14:03
  • Process death occurs on "low memory condition". It means your Activity stack is restored from the Activity Stack Records, and Application instance is recreated as well. All static fields are cleared out unless you persist them manually into a bundle and back. You might think low memory condition is a rare thing, but just run Pokemon Go and Chrome and they kinda kill each other every time (and every other running app) :P – EpicPandaForce Aug 04 '16 at 14:11
  • @EpicPandaForce yeah I know, I have actually quite a low specs smartphone which is a good thing as a developer as I've met this kind of problem already ^^ The question is, what kind of object can I insert in a Bundle/Intent ? I think it has to be serializable.. Well, I will investigate all this. – Louis Durand Aug 04 '16 at 14:35
  • Serializable or Parcelable. – EpicPandaForce Aug 04 '16 at 14:36
  • Using `this` as the `Context` parameter when creating an `Intent` does not cause a memory leak. The `Context` is only used to retrieve the package name of the `Component` to be launched. It is not stored in the `Intent`. – David Wasser Aug 05 '16 at 13:48
  • @DavidWasser oh ok seems legit then. But why does it matter if we pass an Application or an Activity then if it's just about retrieving the package's name? Thanks though. – Louis Durand Aug 05 '16 at 23:10
  • In this case, it doesn't matter. As I said, you can use any `Context` you want in the 2-argument `Intent` constructor. It makes absolutely no difference. – David Wasser Aug 06 '16 at 15:14
  • @DavidWasser funny enough, I've seen a bunch of articles/posts about scope related stuff and that Activities SHOULD be used to start another activity on top of it. And now you tell me it's exactly the same?? – Louis Durand Aug 06 '16 at 23:01
  • Don't believe everything you read. The source code for Android is available to browse on `grepcode.com`. Look for yourself. Or just think: You don't need a `Context` to start another `Activity` with an `Intent`. You can create an `Intent` using the single-argument constructor, which just sets the ACTION. – David Wasser Aug 07 '16 at 08:35

1 Answers1

1

So...

  1. Static vars are located in the perm-gen area. In plain English - they're all kept in a designated area in the heap. More here: static allocation in java - heap, stack and permanent generation

  2. So your Activity2.co object will not be garbage collected, regardless of either Activity1 or Activity2's state. This is not exactly a "leak", but once set - the object will occupy memory for the duration of the process' life.

  3. Android may anytime "kill" an Activity in order to free memory. Activitys are supposed to maintain their state via a savedState object. More here: https://developer.android.com/training/basics/activity-lifecycle/recreating.html

  4. So storing static objects might not be the right way to pass data between Activitys. Here is a discussion on the alternatives: How do I pass data between Activities in Android application?

Community
  • 1
  • 1
Vaiden
  • 15,728
  • 7
  • 61
  • 91