How to send objects through bundle

173,145

Solution 1

Figuring out what path to take requires answering not only CommonsWare's key question of "why" but also the question of "to what?" are you passing it.

The reality is that the only thing that can go through bundles is plain data - everything else is based on interpretations of what that data means or points to. You can't literally pass an object, but what you can do is one of three things:

1) You can break the object down to its constitute data, and if what's on the other end has knowledge of the same sort of object, it can assemble a clone from the serialized data. That's how most of the common types pass through bundles.

2) You can pass an opaque handle. If you are passing it within the same context (though one might ask why bother) that will be a handle you can invoke or dereference. But if you pass it through Binder to a different context it's literal value will be an arbitrary number (in fact, these arbitrary numbers count sequentially from startup). You can't do anything but keep track of it, until you pass it back to the original context which will cause Binder to transform it back into the original handle, making it useful again.

3) You can pass a magic handle, such as a file descriptor or reference to certain os/platform objects, and if you set the right flags Binder will create a clone pointing to the same resource for the recipient, which can actually be used on the other end. But this only works for a very few types of objects.

Most likely, you are either passing your class just so the other end can keep track of it and give it back to you later, or you are passing it to a context where a clone can be created from serialized constituent data... or else you are trying to do something that just isn't going to work and you need to rethink the whole approach.

Solution 2

You can also use Gson to convert an object to a JSONObject and pass it on bundle. For me was the most elegant way I found to do this. I haven't tested how it affects performance.

In Initial Activity

Intent activity = new Intent(MyActivity.this,NextActivity.class);
activity.putExtra("myObject", new Gson().toJson(myobject));
startActivity(activity);

In Next Activity

String jsonMyObject;
Bundle extras = getIntent().getExtras();
if (extras != null) {
   jsonMyObject = extras.getString("myObject");
}
MyObject myObject = new Gson().fromJson(jsonMyObject, MyObject.class);

Solution 3

The Parcelable interface is a good way to pass an object with an Intent.

How can I make my custom objects Parcelable? is a pretty good answer on how to use Parcelable

The official google docs also include an example

Solution 4

You could use the global application state.

Update:

Customize and then add this to your AndroidManifest.xml :

<application android:label="@string/app_name" android:debuggable="true" android:name=".CustomApplication"

And then have a class in your project like this :

package com.example;

import android.app.Application;

public class CustomApplication extends Application {
    public int someVariable = -1;
}

And because "It can be accessed via getApplication() from any Activity or Service", you use it like this:

CustomApplication application = (CustomApplication)getApplication();
application.someVariable = 123; 

Hope that helps.

Solution 5

You can also make your objects Serializable and use the Bundle's getSerializable and putSerializable methods.

Share:
173,145
ahodder
Author by

ahodder

I'm a derp who derps with herps in hopes that the herp does all the derping I want it to.

Updated on September 17, 2020

Comments

  • ahodder
    ahodder almost 4 years

    I need to pass a reference to the class that does the majority of my processing through a bundle.

    The problem is it has nothing to do with intents or contexts and has a large amount of non-primitive objects. How do I package the class into a parcelable/serializable and pass it to a startActivityForResult?

  • ahodder
    ahodder over 13 years
    Thanks for the reply, but how?
  • Mark Storer
    Mark Storer over 13 years
    I believe you just subclass Application and can then store anything you like. The xml changes you need are mentioned in the above link.
  • dhaag23
    dhaag23 over 13 years
    As a general design principal, it's a good idea to avoid globals unless you really need them. In this case there are good alternatives.
  • ahodder
    ahodder over 13 years
    Thanks for tour reply. Your right, all I need to do is just pass a reference of a list of objects to my new activity. The new activity will take some data from the list and display a selectable ListView. onSelect,the activity will return a result (some data pertaining to the click object) to the host activity. If I understand correctly, I believe your option 2 handles this most appropriately; how do I get this opaque handle?
  • ahodder
    ahodder over 13 years
    I tried that and quickly realized it would be impractical. I don't think most of the objects stored in passed class (threads) are serializable. :) thanks though.
  • ahodder
    ahodder over 13 years
    Ok, I think I get what you are saying. Just extend Application and throw in a variable holding the object that needs to be passed; I reviewed the reference page and didn't see the necessary xml changes.
  • Chris Stratton
    Chris Stratton over 13 years
    Your other activity can't extract any data from an opaque object to display. What you probably want to do is create and pass across some surrogate objects of a supported type which contain copies of the information that would be displayed.
  • Mario Lenci
    Mario Lenci over 11 years
    this looks smooth and easy looking at the code. But i feel there is something more on why the SDK doesn't offer something like this to pass objects. Can you tell me something more on this solution?
  • britzl
    britzl over 11 years
    Since it's a matter of passing stuff between activities it doesn't happen often enough to have great impact on the overall performance of the app. That being said I doubt it would work to serialize the DataManager of the original post since it sounds like it has socket connections and other similar classes.
  • ahodder
    ahodder over 11 years
    Well, with something like a Date, you could just pass the long value. But, the rest sounds good. Thanks.
  • Risadinha
    Risadinha about 11 years
    No need at all for all that code! Use bundle.putSerializable(objectImplementingSerializable) - this does underneath what your are re-implementing here again...
  • Jeffrey Blattman
    Jeffrey Blattman almost 11 years
    or they can also be serializable as well.
  • saiyancoder
    saiyancoder over 10 years
    But considerably reduces performance 10x!! Check out this benchmark: developerphil.com/parcelable-vs-serializable
  • pinoyyid
    pinoyyid over 10 years
    +1 @Mati's comment, however to put it into context 10x when applied to a single object is the equivalent of 1 ms. So perhaps not as bad as it sounds.
  • saiyancoder
    saiyancoder over 10 years
    Agree. The problem is when you deal with collections, which is a very common use case if you are getting resources from a Rest API. But for a single object, shouldn't be something notorious. Anyway, if all the boilerplate code is something getting in your way, you can try this lib that generates that all for you: github.com/johncarl81/parceler. A really nice approach!
  • Igor Čordaš
    Igor Čordaš over 10 years
    I wanted to write this as an answer too. This is definitely one of the ways to do it. But keep in mind that these objects stay in the memory unless you de-refrence them (or App context is destroyed) and can be occupying space when you don't need them.
  • Gallal
    Gallal about 10 years
    Broken link: 404 (not found)
  • TechNyquist
    TechNyquist over 9 years
    Also Google suggests this solution instead of Serialize: check out the last section "Recommended Alternatives" of this doc page
  • jiduvah
    jiduvah over 9 years
    just as a word of warning, I followed this technique for a while but there is a memory limit to what you can pass as a String so be sure your data isn't too big.
  • geekQ
    geekQ almost 8 years
    See blog.madadipouya.com/2015/09/21/… to learn how to add Gson support to your project.
  • Rohit Mandiwal
    Rohit Mandiwal almost 8 years
    Smart solution, hats off to you!
  • Abdennacer Lachiheb
    Abdennacer Lachiheb over 7 years
    MyObject myObject ... is not always functional, i tried for an object and it show me parsing error message.
  • raphaelbgr
    raphaelbgr about 7 years
    This is not a good idea, since it uses Reflaction, bad for performance =( Use Parceleable instead.