我需要通过一个包传递对完成我大部分处理的类的引用。
问题是它与意图或上下文无关,并且有大量的非原始对象。如何将类打包成可打包/可序列化并将其传递给startActivityForResult
?
我需要通过一个包传递对完成我大部分处理的类的引用。
问题是它与意图或上下文无关,并且有大量的非原始对象。如何将类打包成可打包/可序列化并将其传递给startActivityForResult
?
您还可以使用 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);
弄清楚要走哪条路不仅需要回答 CommonsWare 的“为什么”这个关键问题,还需要回答“走向什么?”的问题。你通过了吗?
现实情况是,唯一可以通过捆绑包的是普通数据 - 其他一切都基于对数据含义或指向的解释。你不能从字面上传递一个对象,但你可以做的是以下三件事之一:
1)你可以把对象分解成它的构成数据,如果另一端知道同一种对象,它可以从序列化的数据中组装一个克隆。这就是大多数常见类型通过捆绑包的方式。
2)你可以传递一个不透明的句柄。如果您在相同的上下文中传递它(尽管有人可能会问为什么要麻烦),那将是一个您可以调用或取消引用的句柄。但是如果你通过 Binder 将它传递给不同的上下文,它的文字值将是一个任意数字(实际上,这些任意数字从启动开始按顺序计数)。除了跟踪它之外,您什么也做不了,直到您将它传递回原始上下文,这将导致 Binder 将其转换回原始句柄,使其再次有用。
3)您可以传递一个魔术句柄,例如文件描述符或对某些操作系统/平台对象的引用,如果您设置正确的标志,Binder 将为接收者创建一个指向相同资源的克隆,这实际上可以用于另一端。但这仅适用于极少数类型的对象。
最有可能的是,您要么传递您的类,以便另一端可以跟踪它并稍后将其返回给您,或者您将其传递给可以从序列化的组成数据创建克隆的上下文......或者其他您正在尝试做一些行不通的事情,您需要重新考虑整个方法。
您可以使用全局应用程序状态。
更新:
自定义然后将其添加到您的 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 = 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{ }
通过捆绑发送对象的另一种方法是使用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;
}
希望对其他小伙伴有所帮助。
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");
当我在寻找一种传递 Date 对象的方法时,我遇到了这个问题。就我而言,正如答案中所建议的那样,我使用了 Bundle.putSerializable() ,但这不适用于原始帖子中描述的 DataManager 的复杂事物。
我的建议是使用依赖注入并将 DataManager 绑定到 Singleton 范围并在需要的地方注入 DataManager,这与将所述 DataManager 放入 Application 或使其成为 Singleton 的结果非常相似。您不仅可以获得可测试性提高的好处,而且您还可以获得更简洁的代码,而无需所有样板“在类和活动之间传递依赖关系”代码。(Robo)Guice非常易于使用,新的Dagger框架看起来也很有前途。
这是对我自己的问题的一个非常迟的答案,但它一直受到关注,所以我觉得我必须解决它。这些答案中的大多数都是正确的,并且可以完美地处理这项工作。但是,这取决于应用程序的需要。此答案将用于描述此问题的两种解决方案。
服务是一个应用程序组件,可以在 背景并且不提供用户界面。服务很简洁,因为它们具有更明确的生命周期,更容易控制。此外,如果需要,服务可以在应用程序外部运行(即在启动时)。这对于某些应用程序或只是一个简洁的功能可能是必需的。
这不是对两者的完整描述,但我为那些想要进行更多调查的人留下了文档的链接。总的来说,Service
这对于我需要的实例来说更好——在我的 SPP 设备上运行一个 ServerSocket。
另一种使用捆绑传递对象的简单方法: