Reputation: 11439
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
?
Upvotes: 121
Views: 178233
Reputation: 2044
1.A very direct and easy to use example, make object to be passed implement Serializable.
class Object implements Serializable{
String firstName;
String lastName;
}
2.pass object in bundle
Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);
3.get passed object from bundle as Serializable then cast to Object.
Object object = (Object) getArguments().getSerializable("object");
Upvotes: 4
Reputation: 119
Possible solution:
Bundle bundle = new Bundle();
bundle.putSerializable("key", new CustomObject());
Class CustomObject:
class CustomObject implements Serializable{
private SubCustomObject1 sc1;
private SubCustomObject2 sc2;
}
Subcustom objects:
class SubCustomObject1 implements Serializable{ }
class SubCustomObject2 implements Serializable{ }
Upvotes: 11
Reputation: 473
another simple way to pass object using a bundle:
Upvotes: 0
Reputation: 1045
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
Upvotes: 22
Reputation: 2296
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.
Upvotes: 13
Reputation: 2622
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);
Upvotes: 160
Reputation: 10242
I came across this question when I was looking for a way to pass a Date object. In my case, as was suggested among the answers, I used Bundle.putSerializable() but that wouldn't work for a complex thing as the described DataManager in the original post.
My suggestion that will give a very similar result to putting said DataManager in the Application or make it a Singleton is to use Dependency Injection and bind the DataManager to a Singleton scope and inject the DataManager wherever it is needed. Not only do you get the benefit of increased testability but you'll also get cleaner code without all of the boiler plate "passing dependencies around between classes and activities" code. (Robo)Guice is very easy to work with and the new Dagger framework looks promising as well.
Upvotes: 1
Reputation: 12302
One More way to send objects through bundle is by using bundle.putByteArray
Sample code
public class DataBean implements Serializable {
private Date currentTime;
public setDate() {
currentTime = Calendar.getInstance().getTime();
}
public Date getCurrentTime() {
return currentTime;
}
}
put Object of DataBean in to Bundle:
class FirstClass{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...
//When you want to start new Activity...
Intent dataIntent =new Intent(FirstClass.this, SecondClass.class);
Bundle dataBundle=new Bundle();
DataBean dataObj=new DataBean();
dataObj.setDate();
try {
dataBundle.putByteArray("Obj_byte_array", object2Bytes(dataObj));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dataIntent.putExtras(dataBundle);
startActivity(dataIntent);
}
Converting objects to byte arrays
/**
* Converting objects to byte arrays
*/
static public byte[] object2Bytes( Object o ) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream( baos );
oos.writeObject( o );
return baos.toByteArray();
}
Get Object back from Bundle:
class SecondClass{
DataBean dataBean;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...
//Get Info from Bundle...
Bundle infoBundle=getIntent().getExtras();
try {
dataBean = (DataBean)bytes2Object(infoBundle.getByteArray("Obj_byte_array"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Method to get objects from byte arrays:
/**
* Converting byte arrays to objects
*/
static public Object bytes2Object( byte raw[] )
throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream( raw );
ObjectInputStream ois = new ObjectInputStream( bais );
Object o = ois.readObject();
return o;
}
Hope this will help to other buddies.
Upvotes: 7
Reputation: 11439
This is a very belated answer to my own question, but it keep getting attention, so I feel I must address it. Most of these answers are correct and handle the job perfectly. However, it depends on the needs of the application. This answer will be used to describe two solutions to this problem.
A Service is an application component that can perform long-running operations in the background and does not provide a user interface.Services are neat in that they have a more defined lifecycle that is easier to control. Further, if needed, services can run externally of the application (ie. on boot). This can be necessary for some apps or just a neat feature.
This wasn't a full description of either, but I left links to the docs for those who want to investigate more. Overall the Service
is the better for the instance I needed - running a ServerSocket to my SPP device.
Upvotes: 0
Reputation: 40397
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.
Upvotes: 56
Reputation: 6126
You can also make your objects Serializable and use the Bundle's getSerializable and putSerializable methods.
Upvotes: 13