如何通过捆绑发送对象

我需要将一个引用传递给通过一个bundle执行我的大部分处理的类。

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

确定采取什么样的path,不仅需要回答CommonsWare关于“为什么”的关键问题,还要回答“到什么”的问题。 你通过它吗?

事实上,唯一可以通过捆绑的东西就是明文数据 – 其他的一切都是基于对数据意味着什么的指导。 你不能从字面上传递一个对象,但你可以做的是三件事情之一:

1)你可以把对象分解成它的构成数据,如果对方有什么知识,就可以从序列化的数据中组装一个克隆。 这就是大多数常见types通过绑定的方式。

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

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

最有可能的是,你要么传递你的类,所以另一端可以跟踪它,稍后再给你,或者你传递给一个上下文,从序列化的组件数据创build一个克隆…或者你正在尝试做一些没有用的东西,你需要重新思考整个方法。

您还可以使用Gson将对象转换为JSONObject并将其传递给bundle。 对我来说是我发现的最优雅的方式。 我没有testing它是如何影响性能的。

在初始活动

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

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

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

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

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

更新:

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

希望有所帮助。

你也可以使你的对象可序列化,并使用Bundle的getSerializable和putSerializable方法。

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

从包中获取对象:

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

希望这会有助于其他的朋友。

可能的scheme

 Bundle bundle = new Bundle(); bundle.putSerializable(new CustomObject()); 

类CustomObject:

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

子自定义对象:

 class SubCustomObject1 implements Serializable{ } class SubCustomObject2 implements Serializable{ } 

我也想推荐这个优秀的博客文章,比较所有不同的选项和他们的性能影响

对于我自己的问题来说,这是一个非常迟缓的答案,但是它一直受到关注,所以我觉得我必须解决它。 这些答案中的大部分是正确的,完美地处理工作。 但是,这取决于应用程序的需求。 这个答案将被用来描述这个问题的两个解决scheme。

应用

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

服务

“ 服务”是第二位。 “服务”实际上是我的问题的更好的select,因为这是服务的目的:

服务是一个可以执行长时间运行的应用程序组件
背景并且不提供用户界面。

服务是整洁的,因为他们有一个更容易控制的更明确的生命周期。 此外,如果需要,服务可以在应用程序的外部运行(即在启动时)。 这可能是一些应用程序或只是一个整洁的function所必需的。

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

当我正在寻找一种传递Date对象的方法时,我遇到了这个问题。 在我的情况下,正如在答案中所暗示的那样,我使用了Bundle.putSerializable(),但是对于复杂的东西来说,这并不适用于原始文章中描述的DataManager。

我的build议是将DataManager放到应用程序中,或者使它成为一个Singleton,这个结果与使用dependency injection并将DataManager绑定到一个Singleton作用域,并在需要的地方注入DataManager是非常相似的。 您不仅可以获得提高可testing性的好处,而且还可以获得更清晰的代码,而无需使用“在类和活动之间传递依赖关系”的代码。 (Robo)Guice非常容易使用,而且新的Dagger框架也很有前途。

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

  • 在类对象中,用一个键创build一个静态列表或另一个数据结构
  • 当你创build这个对象的时候,把它放在列表/数据结构中,使用键(例如创build对象时的长时间戳)
  • 创build方法static getObject(long key)从列表中获取对象
  • 在包中传递密钥,所以你可以从代码中的其他位置获取对象