如何通过包发送对象

如何通过包发送对象

问题描述:

我需要将引用传递给通过包执行我大部分处理的类。如何通过包发送对象

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

+2

“我需要将引用传递给通过绑定执行大部分处理的类” - 为什么? – CommonsWare 2010-11-22 20:27:24

+1

我有一个对象(DataManager),它处理一个服务器并为一些GUI运行几个后端。当建立新的连接时,我希望用户能够启动一个新的活动,该活动在ListView中列出所有活动连接并让用户选择一个。结果数据然后将绑定到新的GUI。这真的只是后端的皮肤选择器。 – AedonEtLIRA 2010-11-23 18:11:25

+3

如果您通过多个活动处理同一个对象实例,您可能需要考虑[singleton pattern](http://en.wikipedia.org/wiki/Singleton_pattern)。有一个很好的教程[这里](http://www.javaworld.com/article/2073352/core-java/simply-singleton.html)。 – sotrh 2014-07-22 21:31:51

找出需要采取的措施不仅需要回答CommonsWare关于“为什么”的关键问题,还需要回答“到什么”的问题。你通过它吗?

现实情况是,唯一可以通过捆绑的东西是明文数据 - 其他所有内容都基于对数据意味着什么或指向什么的解释。你不能从字面上传递一个对象,但你可以做的是以下三件事之一:

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

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

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

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

您可以使用全局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; 

希望有所帮助。

+0

感谢您的回复,但是如何? – AedonEtLIRA 2010-11-22 20:54:18

+0

我相信你只是应用子类,然后可以存储任何你喜欢的东西。您需要的xml更改在上面的链接中提到。 – 2010-11-22 21:58:55

+9

作为一般的设计主体,除非你确实需要它们,否则避免使用全局变量是个好主意。在这种情况下,有很好的选择。 – dhaag23 2010-11-22 22:31:08

可以分页接口是一种用Intent传递对象的好方法。

How can I make my custom objects Parcelable?是关于如何使用Parcelable

一个很好的答案官方google docs还包括例如

您也可以让你的对象Serializable并使用捆绑的getSerializableputSerializable方法。

对于我自己的问题,这是一个很迟来的答案,但它一直引起注意,所以我觉得我必须解决它。这些答案中的大部分都是正确的,并且完美地处理这项工作但是,这取决于应用程序的需求。这个答案将被用来描述这个问题的两个解决方案。

应用

首先是 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设备。

再来通过束发送对象的方法是使用
示例代码

public class DataBean implements Serializable { 
private Date currentTime; 

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

public Date getCurrentTime() { 
    return currentTime; 
} 
} 

公司Databean的PUT物件在捆绑:

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

希望这将有助于其他好友。

您也可以使用Gson将对象转换为JSONObject并在捆绑上传递它。对我而言,我发现这是最优雅的方式。我没有测试它如何影响性能。

在初始活性

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.putSerializable(),但这不适用于原始文章中描述的DataManager这样复杂的事情。

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

我也想推荐这个优秀的Blog邮报,比较各种不同的选项,其性能的影响

可能的解决方案:

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

类CustomObject:

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

Subcustom对象:

class SubCustomObject1 implements Serializable{ } 

class SubCustomObject2 implements Serializable{ } 

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

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