121

我需要通过一个包传递对完成我大部分处理的类的引用。

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

4

11 回答 11

160

您还可以使用 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);
于 2013-02-01T12:09:02.707 回答
56

弄清楚要走哪条路不仅需要回答 CommonsWare 的“为什么”这个关键问题,还需要回答“走向什么?”的问题。你通过了吗?

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

1)你可以把对象分解成它的构成数据,如果另一端知道同一种对象,它可以从序列化的数据中组装一个克隆。这就是大多数常见类型通过捆绑包的方式。

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

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

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

于 2010-11-23T05:32:16.050 回答
22

Parcelable接口是通过Intent传递对象的好方法。

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

官方的谷歌文档还包括一个例子

于 2010-11-22T21:47:43.730 回答
14

您可以使用全局应用程序状态。

更新:

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

并且因为“它可以通过 getApplication() 从任何 Activity 或 Service 访问”,所以您可以这样使用它:

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

希望有帮助。

于 2010-11-22T20:33:45.983 回答
13

您还可以使您的对象可序列化并使用 Bundle 的getSerializableputSerializable方法。

于 2010-11-22T22:29:48.377 回答
11

可能的解决方案:

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

类自定义对象:

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

子自定义对象:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }
于 2015-12-14T15:10:26.760 回答
7

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

public class DataBean implements Serializable {
private Date currentTime;

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

public Date getCurrentTime() {
    return currentTime;
 }
}

将 DataBean 的对象放入 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;
    }

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

于 2012-12-11T11:18:28.413 回答
4

1.一个非常直接好用的例子,使要传递的对象实现Serializable。

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

2.通过包中的对象

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

3.从包中获取传递的对象作为可序列化然后转换为对象。

Object object = (Object) getArguments().getSerializable("object");
于 2018-08-20T22:55:33.273 回答
1

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

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

于 2013-02-07T20:41:59.947 回答
0

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

应用

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

服务

服务是第二 的。对于我的问题,“服务”实际上是更好的选择,因为这就是服务的设计目的:
服务是一个应用程序组件,可以在
背景并且不提供用户界面。
服务很简洁,因为它们具有更明确的生命周期,更容易控制。此外,如果需要,服务可以在应用程序外部运行(即在启动时)。这对于某些应用程序或只是一个简洁的功能可能是必需的。

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

于 2012-09-07T16:22:38.030 回答
0

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

  • 在类对象中,创建一个静态列表或另一个带有键的数据结构
  • 创建对象时,将其放入带有键的列表/数据结构中(例如,创建对象时的长时间戳)
  • 创建方法 static getObject(long key) 从列表中获取对象
  • 在捆绑包中传递密钥,因此您可以稍后从代码中的另一点获取对象
于 2015-12-24T09:46:00.620 回答