126

I need to be able to use one object in multiple activities within my app, and it needs to be the same object. What is the best way to do this?

I have tried making the object "public static" so it can be accessed by other activities, but for some reason this just isn't cutting it. Is there another way of doing this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mtmurdock
  • 12,756
  • 21
  • 65
  • 108

6 Answers6

142

When you are creating an object of intent, you can take advantage of following two methods for passing objects between two activities.

putParcelable

putSerializable

You can have your class implement either Parcelable or Serializable. Then you can pass around your custom classes across activities. I have found this very useful.

Here is a small snippet of code I am using

CustomListing currentListing = new CustomListing();
Intent i = new Intent();
Bundle b = new Bundle();
b.putParcelable(Constants.CUSTOM_LISTING, currentListing);
i.putExtras(b);
i.setClass(this, SearchDetailsActivity.class);
startActivity(i);

And in newly started activity code will be something like this...

Bundle b = this.getIntent().getExtras();
if (b != null)
    mCurrentListing = b.getParcelable(Constants.CUSTOM_LISTING);
spaaarky21
  • 6,524
  • 7
  • 52
  • 65
anargund
  • 3,249
  • 2
  • 21
  • 25
  • 2
    I solved this problem ages ago, but I thought your answer was worth accepting. – mtmurdock Oct 28 '11 at 01:40
  • Can you tell me how you implemented the Parcelable methods? currentListing should be of type Parcelable right? – Namratha Jun 11 '12 at 08:13
  • Yes, you would have to implement an interface Parcelable and provide implementations. So it basically has methods for creating an actual object from the parcel and write data to the parcel. – anargund Jun 11 '12 at 23:48
  • CUSTOM_LISTING cannot be resolved or is not a field. – Oliver Dixon Jul 02 '12 at 17:35
  • 4
    Of course, its from my own class, its not a Standard android class. All I am saying is use some constant as a key! – anargund Jul 02 '12 at 22:39
  • 6
    Is there a reason you put a `Bundle` as the extra in `i.putExras(b)` instead of simply putting the `Parcelable` object directly via [`Intent.putExtra(String name,Parcelable value)`](http://developer.android.com/reference/android/content/Intent.html#putExtra(java.lang.String,android.os.Parcelable)) and then retrieving via [`Intent.getParcelableExtra(String name)`](http://developer.android.com/reference/android/content/Intent.html#getParcelableExtra(java.lang.String))? – Tony Chan Aug 02 '13 at 22:57
  • 1
    I can highly recommend the [Parceler library](https://github.com/johncarl81/parceler) to handle parceling of objects – Till - Appviewer.io Feb 05 '15 at 10:28
  • And if you use Android Studio, I recommend Android Parcelable code generator (https://plugins.jetbrains.com/plugin/7332?pr=idea) which allows to implement Parcelable methods using the Generate context menu – Andrei Drynov Apr 23 '15 at 09:32
37

You can create a subclass of Application and store your shared object there. The Application object should exist for the lifetime of your app as long as there is some active component.

From your activities, you can access the application object via getApplication().

Erich Douglass
  • 51,744
  • 11
  • 75
  • 60
  • 3
    Ok this is new to me. how would i implement that? – mtmurdock May 25 '10 at 19:20
  • What i ended up actually doing was making the object a protected member of my startup activity and then referenced the variable from other activities directly. This isn't exactly Erich's answer but it was his answer that gave me the idea – mtmurdock Jun 19 '10 at 04:22
  • How do you set the subclass of Application as your application? @mtmurdock How did you pass the instance of your first activity to the others? – Tenfour04 Feb 11 '11 at 01:20
  • 2
    @TenFour04 Set it via the element in your manifest. – Erich Douglass Feb 11 '11 at 01:24
  • 2
    @TenFour04 This was a long time ago and my methods have changed a lot. I have found lots of ways around this. Anything from Singleton objects which are accessable via class accessors, to implementing the Serializable interface. Basically instead of trying to sidestep the problem, I endorsed Google's methodology. However, if the object in question needs to exist at the application scope, @Erich's answer is a great solution. – mtmurdock Jun 01 '11 at 21:39
  • I think this is a very bad idea. The Application object and any subclass is not responsible for holding data but only for basic initialization of the app. Use the Preferences, a memory cache (Singleton), database, Realm or whatever. But not a subclassed application: – GabrielWeis Mar 29 '16 at 10:42
  • Same as static field – k4dima Feb 27 '17 at 14:50
  • 1
    I also think this is a bad idea as the Application object gets destroyed with all its local variables when the app process is killed. When the user wants to open the app again from the recent apps stack it recreates the last displayed activity. If this activity depends on previously stored values in the Application object you will run into problems as those values aren't there anymore. For more information refer to this blog post: [Don't Store Data in the Application Object](http://www.developerphil.com/dont-store-data-in-the-application-object/) – BrickTop Apr 03 '17 at 14:06
  • These are important points about the limitations of using the Application object, but that doesn't mean that using an Application object is always "a bad idea." Each of the alternatives @Gabriel mentioned has its own limitations and drawbacks. Singleton objects are basically equivalent to using the Application object. The other methods require the data to be serializable. – LarsH Jul 29 '17 at 03:21
36

This answer is specific to situations where the objects to be passed has nested class structure. With nested class structure, making it Parcelable or Serializeable is a bit tedious. And, the process of serialising an object is not efficient on Android. Consider the example below,

class Myclass    {
  int a;
  class SubClass    {
       int b;
  }
}

With Google's GSON library, you can directly parse an object into a JSON formatted String and convert it back to the object format after usage. For example,

MyClass src = new MyClass();
Gson gS = new Gson();
String target = gS.toJson(src); // Converts the object to a JSON String

Now you can pass this String across activities as a StringExtra with the activity intent.

Intent i = new Intent(FromActivity.this, ToActivity.class);
i.putExtra("MyObjectAsString", target);

Then in the receiving activity, create the original object from the string representation.

String target = getIntent().getStringExtra("MyObjectAsString");
MyClass src = gS.fromJson(target, MyClass.class); // Converts the JSON String to an Object

It keeps the original classes clean and reusable. Above of all, if these class objects are created from the web as JSON objects, then this solution is very efficient and time saving.

UPDATE


While the above explained method works for most situations, for obvious performance reasons, do not rely on Android's bundled-extra system to pass objects around. There are a number of solutions makes this process flexible and efficient, here are a few. Each has its own pros and cons.

  1. Eventbus
  2. Otto
Community
  • 1
  • 1
C--
  • 16,393
  • 6
  • 53
  • 60
7

Maybe it's an unpopular answer, but in the past I've simply used a class that has a static reference to the object I want to persist through activities. So,

public class PersonHelper
{
    public static Person person;
}

I tried going down the Parcelable interface path, but ran into a number of issues with it and the overhead in your code was unappealing to me.

Chris Stewart
  • 3,303
  • 9
  • 36
  • 55
  • This is a great solution, but isn't always the best choice. If you don't like Parcelable and if your object can be reduced to primitives (int, float, double, boolean) and Strings, then implementing the Serializable interface is very easy to do. Virtually no work on your part, and has very little overhead. – mtmurdock Jun 01 '11 at 21:44
  • 1
    @mtmurdock: is the serialzed object a 'snapshot' of the state when serializing? I need to pass an Object to a service, which changes in the runtime of the service. The service should always use the up-to-date object, not an old, quasi-copied object. – stk Jul 07 '11 at 14:29
  • 1
    @stk Yes, the serialize object is a snapshot. More accurately it is a copy, which means changing it in one activity will not affect the other activity unless you pass it back. A service is a fine way to go, but I can understand why someone would feel that is kind of overkill. Another solution is to save your data using the persistent object storage built into Android. It may or may not suit your needs, but if you need to be able to get/set values across your entire app, its not a bad solution and can be used to save persistent data. – mtmurdock Jul 08 '11 at 16:22
6

It depends on the type of data you need access to. If you have some kind of data pool that needs to persist across Activitys then Erich's answer is the way to go. If you just need to pass a few objects from one activity to another then you can have them implement Serializable and pass them in the extras of the Intent to start the new Activity.

CaseyB
  • 24,780
  • 14
  • 77
  • 112
  • This is probably the best solution as long as your objects dont need to persist over the life of the application (which is covered by @Erich Douglas' answer). – mtmurdock Jun 01 '11 at 21:41
6

Your object can also implement the Parcelable interface. Then you can use the Bundle.putParcelable() method and pass your object between activities within intent.

The Photostream application uses this approach and may be used as a reference.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fedor
  • 43,261
  • 10
  • 79
  • 89