如何通过bundle发送对象

问题描述 投票:112回答:11

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

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

android serialization android-activity bundle parcelable
11个回答
54
投票

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

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

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

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

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

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


0
投票

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

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


0
投票

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

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

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

19
投票

Parcelable接口是使用Intent传递对象的好方法。

How can I make my custom objects Parcelable?是如何使用Parcelable的一个很好的答案

官方google docs也包括一个例子


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; 

希望有所帮助。


11
投票

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


9
投票

可能的方法:

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

7
投票

通过bundle发送对象的另一种方法是使用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;
    }

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


1
投票

1.一个非常直接易用的例子,使对象传递工具Serializable。

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

2.在bundle中传递对象

Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);
  1. 从bundle中传递对象作为Serializable然后转换为Object。 Object object =(Object)getArguments()。getSerializable(“object”);

0
投票

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

Application

The first is the Application, as it has been the most spoken about answer here. The application is a good object to place entities that need a reference to a Context. A `ServerSocket` undoubtedly would need a context (for file I/o or simple `ListAdapter` updates). I, personally, prefer this route. I like application's, they are useful for context retrieving (because they can be made static and not likely cause a memory leak) and have a simple lifecycle.

Service

The Service` 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.
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.

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

© www.soinside.com 2019 - 2024. All rights reserved.