maphongba008
maphongba008

Reputation: 2353

Is it OK to pass object between activities using Application class?

I know how to pass object using Parcelable or Serializable but I found other approach on the internet to do it - using Application class like this:

class ComplexObject {
    // contain String, int, List<String>, other objects ...
}

class App extends Application {

    Map<String, Object> map = new HashMap<>();

    public void put(String key, Object value) {
        map.put(key, value);
    }

    public <T> T get(String key, Class<T> cls) {
        return cls.cast(map.get(key));
    }

    public void remove(String key) {
        map.remove(key);
    }

}

class ActivityA extends AppCompatActivity {

    void start(ComplexObject obj) {
        Intent intent = new Intent(this, ActivityB.class);
        ((App) getApplicationContext()).put("obj", obj);
        startActivity(intent);
    }

}


class ActivityB extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        App app = ((App) getApplicationContext());
        ComplexObject obj = app.get("obj", ComplexObject.class);
        app.remove("obj");
    }
}

Is this impact performance of app?

Upvotes: 1

Views: 139

Answers (2)

Alessio
Alessio

Reputation: 3173

No it's not OK at all.

Except for cases when the instantiated object is very very big (say 20MB or more), where you want to find alternative solutions, for 'normal' objects you should use Parcelables and Bundles to pass them between activities. That's the system design.

You seem to ignore a very important comment on Application:

Note: There is normally no need to subclass Application. In most situations, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), include Context.getApplicationContext() as a Context argument when invoking your singleton's getInstance() method.

As I see it, you're fighting against the system, and you should really have a good reason for that. Passing objects like you're suggesting can also expose you to memory leaks, depending on the object, so be very careful.

Last but not least, and without knowing the details, you should consider why an activity is creating such an object, but another one is using it.

Upvotes: 0

David Wasser
David Wasser

Reputation: 95578

You can also do this using static members in any class (you don't need to extend Application in order to do this.

You can also store data in some persistent storage (File, SharedPreferences, SQLite database, etc.) to do this.

There are pros and cons. Here's my take on this:

From a "performance" perspective, passing a reference to an existing object by using your Application code or by using a static member variable is significantly faster than serializing an object into a Bundle and deserializing it again (using either Serializable or Parcelable). However, unless you have a huge amount of data you are doing this with, you won't be able to notice any performance loss (or gain).

From a "complexity" perspective, passing a reference to an existing object is significantly easier to understand than the serialization and deserialization process. It is also less likely to be buggy.

From a "robustness" perspective, you need to understand that Android can kill the OS process hosting your app at any time. This means that if you are passing data between one Activity and another by passing (or storing) a reference to an existing object, there are cases where the underlying object will be gone by the time the receiving Activity needs it. This can cause your app to crash, or behave unexpectedly, if you don't write code to handle this situation and act accordingly.

From a "correctness" perspective, you should pass any required data between activities as "extras" in the Intent. Android ensures that the "extras" in the Intent are stored persistently so that, in the case where Android kills the OS process hosting your app, when the user returns to the app, Android can recreate everything as it was. That said, you should not pass large amounts of data between activities this way. If you have large amounts of data to pass between activities, the "correct" way to do this is to store the data in a persistent storage (Shared Preferences, SQLite database, File, etc.) and pass enough information (an index or a key) in an Intent "extra" so that the receiving Activity can read the data from the persistent storage.

I tend to take a pragmatic approach and use the method that is most appropriate for the task at hand. There is no one method that is "best" or "correct". To use the classic consultant's answer: "It all depends..."

Upvotes: 2

Related Questions