How to send objects through bundle

我需要传递一个类的引用,该类通过一个 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?

174974 次浏览

您可以使用全局 申请状态。

Update:

自定义,然后将其添加到 AndroidManifest.xml:

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

然后在你的项目中有一个类,像这样:

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;

希望能帮上忙。

可包装的接口是传递具有意图的对象的好方法。

我如何使我的自定义对象 Parcelable? 是一个很好的答案,关于如何使用 < strong > Parcelable

The official 谷歌文档 also include an example

您还可以将对象设置为 可序列化,并使用 Bundle 的 GetSerializerPutSerializer方法。

要想找到解决问题的方法,不仅需要回答 CommsWare 的关键问题“为什么”,还需要回答“为了什么?”你要传球吗。

现实情况是,只有普通数据才能通过捆绑包——其他一切都基于对数据含义或指向的解释。你不能直接传递一个对象,但是你可以做三件事情之一:

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)你可以传递一个不透明的句柄。如果您在相同的上下文中传递它(尽管有人可能会问为什么这么麻烦) ,那将是一个可以调用或取消引用的句柄。但是如果您通过 Binder 将它传递到不同的上下文,那么它的文本值将是一个任意数字(实际上,这些任意数字从启动开始按顺序计数)。除了跟踪它之外,您不能做任何事情,直到您将它传递回原始上下文,这将导致 Binder 将其转换回原始句柄,使其再次有用。

3)你可以传递一个神奇的句柄,比如一个文件描述符或对某些 OS/平台对象的引用,如果你设置了正确的标志,Binder 将创建一个指向收件人相同资源的克隆,这个克隆实际上可以在另一端使用。但这只适用于极少数类型的对象。

最有可能的情况是,你要么传递你的类只是为了让另一端能够跟踪它并在以后返回给你,要么你把它传递到一个上下文中,在这个上下文中可以从序列化的组成数据中创建一个克隆... ... 或者你正在尝试做一些根本不会起作用的事情,你需要重新考虑整个方法。

这是对我自己问题的一个非常迟来的回答,但是它一直受到关注,所以我觉得我必须解决它。这些答案大部分都是正确的,并且处理得很好。但是,这取决于应用程序的需要。这个答案将用来描述这个问题的两种解决方案。

申请

第一个是 申请,因为它是这里谈论最多的答案。应用程序是放置需要引用 Context 的实体的好对象。“ ServerSocket”无疑需要一个上下文(用于文件 I/o 或简单的“ ListAdapter”更新)。我个人比较喜欢这条路线。我喜欢应用程序,它们对于上下文检索很有用(因为它们可以是静态的,不太可能导致内存泄漏) ,并且有一个简单的生命周期。

服务

The 服务 is second. A `Service`is actually the better choice for my problem becuase that is what services are designed to do:
A Service is an application component that can perform long-running operations in
the background and does not provide a user interface.
服务是整洁的,因为它们具有更易于控制的更明确的生命周期。此外,如果需要,服务可以在应用程序的外部运行(即。启动)。这对于某些应用程序来说是必要的,或者仅仅是一个简洁的特性。

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.

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;
}
}

将 DataBean 对象放入捆绑:

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();
}

从 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();
}
}

方法从字节数组中获取对象:

/**
* 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;
}

希望对其他朋友有所帮助。

您还可以使用 Gson 将对象转换为 JSONObject 并在 bundle 上传递它。对我来说,这是我找到的最优雅的方法。我还没测试它是如何影响性能的。

初期活动

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

下一个活动

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

我在寻找传递 Date 对象的方法时遇到了这个问题。在我的例子中,正如在答案中所建议的那样,我使用 Bundle.putSerializer () ,但是对于原文中描述的 DataManager 这样复杂的东西,这种方法不起作用。

我的建议是使用依赖注入,将 DataManager 绑定到 Singleton 作用域,并在需要的任何地方注入 DataManager,这与在应用程序中使用上述 DataManager 或使其成为辛格尔顿非常相似。您不仅可以获得增加的可测试性的好处,而且还可以获得更清晰的代码,而不需要所有“在类和活动之间传递依赖关系”的代码。Guice非常容易使用,新的 匕首框架看起来也很有前途。

可能的解决办法:

Bundle bundle = new Bundle();
bundle.putSerializable("key", new CustomObject());

类 CustomObject:

class CustomObject implements Serializable{
private SubCustomObject1 sc1;
private SubCustomObject2 sc2;
}

次定制对象:

class SubCustomObject1 implements Serializable{ }


class SubCustomObject2  implements Serializable{ }

使用 bundle 传递对象的另一种简单方法:

  • 在类对象中,创建一个静态列表或另一个具有键的数据结构
  • 创建对象时,将其放在具有键(es)的列表/数据结构中。创建对象时的长时间戳)
  • 创建方法 static getObject (长键)以从列表中获取对象
  • 在 bundle 中传递键,以便稍后可以从代码中的另一点获取对象

1.A very direct and easy to use example, make object to be passed implement Serializable.

class Object implements Serializable{
String firstName;
String lastName;
}

在 bundle 中传递对象

Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);

将对象从捆绑包中作为 Serializable 传递给对象,然后转换为 Object。

Object object = (Object) getArguments().getSerializable("object");