如何通过bundle发送对象

时间:2010-11-22 20:25:15

标签: android serialization android-activity bundle parcelable

我需要传递对通过bundle进行大部分处理的类的引用。

问题是它与意图或上下文无关,并且具有大量非基本对象。如何将类打包成parcelable / serializable并将其传递给startActivityForResult

11 个答案:

答案 0 :(得分:150)

您还可以使用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);

答案 1 :(得分:54)

弄清楚要采取什么样的路径不仅要回答CommonsWare关于“为什么”的关键问题,还要回答“为了什么?”的问题。你在路过它吗?

现实情况是,唯一能够通过捆绑的东西是普通数据 - 其他一切都基于对数据的含义或指向的解释。你不能真正传递一个对象,但你可以做的是三件事之一:

1)您可以将对象分解为其构成数据,如果另一端知道相同类型的对象,则可以从序列化数据中组装克隆。这就是大多数常见类型通过bundle的方式。

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

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

最有可能的是,您要么正在传递您的类,要么另一端可以跟踪它并稍后将其返回给您,或者您将其传递给可以从序列化组成数据创建克隆的上下文。或者你正在尝试做一些不起作用的事情,你需要重新考虑整个方法。

答案 2 :(得分:19)

Parcelable 接口是传递具有Intent的对象的好方法。

对于如何使用 Parcelable

How can I make my custom objects Parcelable?是一个非常好的答案

官方google docs还包含一个示例

答案 3 :(得分:14)

您可以使用全局application州。

更新

自定义然后将其添加到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;
}

因为“It can be accessed via getApplication() from any Activity or Service”,你可以这样使用它:

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

希望有所帮助。

答案 4 :(得分:11)

您还可以制作对象Serializable并使用Bundle的getSerializableputSerializable方法。

答案 5 :(得分:9)

可能的解决方案:

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

Class CustomObject:

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

子自定义对象:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }

答案 6 :(得分:7)

通过捆绑包发送对象的另一种方法是使用bundle.putByteArray
<<示例代码

public class DataBean implements Serializable {
private Date currentTime;

public setDate() {
    currentTime = Calendar.getInstance().getTime();
 }

public Date getCurrentTime() {
    return currentTime;
 }
}

将DataBean的Object放入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
 */
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;
    }

希望这对其他伙伴有所帮助。

答案 7 :(得分:1)

1。一个非常直接且易于使用的示例,使要传递的对象实现了Serializable。

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

捆绑包中的2.pass对象

Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);
  1. 从捆绑中获取传递的对象为可序列化对象,然后转换为对象。

    Object object =(Object)getArguments()。getSerializable(“ object”);

答案 8 :(得分:0)

这是对我自己的问题的一个非常迟来的答案,但它一直受到关注,所以我觉得我必须解决它。大多数答案都是正确的,并且完美地处理了这项工作。但是,这取决于应用程序的需求。这个答案将用于描述这个问题的两个解决方案。

的应用

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

服务

Service`是第二名。对于我的问题,“服务”实际上是更好的选择,因为服务的目的是:
A Service is an application component that can perform long-running operations in
the background and does not provide a user interface.
服务很简洁,因为它们具有更易于控制的更明确的生命周期。此外,如果需要,服务可以在应用程序外部运行(即,在启动时)。对于某些应用程序或仅仅是一个简洁的功能,这可能是必要的。

这不是对这两者的完整描述,但我为那些想要进行更多调查的人留下了文档的链接。总的来说,Service对于我需要的实例更好 - 将ServerSocket运行到我的SPP设备。

答案 9 :(得分:0)

当我在寻找传递Date对象的方法时,我遇到了这个问题。在我的情况下,正如答案中所建议的那样,我使用了Bundle.putSerializable(),但这不适用于原始帖子中描述的DataManager这样的复杂事物。

我的建议将给出一个非常相似的结果,将所述DataManager放在Application中或使其成为Singleton是使用依赖注入并将DataManager绑定到Singleton范围并在需要的任何地方注入DataManager。您不仅可以获得提高可测试性的好处,而且还可以获得更清晰的代码,而不需要所有的锅炉板“在类和活动之间传递依赖关系”代码。 (Robo)Guice非常容易使用,新的Dagger框架也很有前途。

答案 10 :(得分:0)

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

  • 在类对象中,使用键
  • 创建静态列表或其他数据结构
  • 创建对象时,将其放在带有键的列表/数据结构中(例如,创建对象时的长时间戳)
  • 创建方法static getObject(long key)以从列表中获取对象
  • bundle中的
  • 传递了密钥,因此您可以稍后从代码中的另一个点获取对象