我需要传递对通过bundle进行大部分处理的类的引用。
问题是它与意图或上下文无关,并且具有大量非基本对象。如何将类打包成parcelable / serializable并将其传递给startActivityForResult
?
答案 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的getSerializable和putSerializable方法。
答案 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);
从捆绑中获取传递的对象为可序列化对象,然后转换为对象。
Object object =(Object)getArguments()。getSerializable(“ object”);
答案 8 :(得分:0)
这是对我自己的问题的一个非常迟来的答案,但它一直受到关注,所以我觉得我必须解决它。大多数答案都是正确的,并且完美地处理了这项工作。但是,这取决于应用程序的需求。这个答案将用于描述这个问题的两个解决方案。
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传递对象的另一种简单方法: