如何通过bundle发送对象

aho*_*der 115 serialization android bundle parcelable android-activity

我需要传递对通过bundle进行大部分处理的类的引用.

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

Lar*_*iro 153

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

在初始活动中

Intent activity = new Intent(MyActivity.this,NextActivity.class);
activity.putExtra("myObject", new Gson().toJson(myobject));
startActivity(activity);
Run Code Online (Sandbox Code Playgroud)

在下一个活动中

String jsonMyObject;
Bundle extras = getIntent().getExtras();
if (extras != null) {
   jsonMyObject = extras.getString("myObject");
}
MyObject myObject = new Gson().fromJson(jsonMyObject, MyObject.class);
Run Code Online (Sandbox Code Playgroud)

  • 此外,谷歌建议使用此解决方案而不是序列化:查看[本文档页面]的最后一节"推荐替代方案"(http://developer.android.com/reference/java/io/Serializable.html) (4认同)
  • 由于这是在活动之间传递内容的问题,因此通常不会对应用程序的整体性能产生很大影响.话虽如此,我怀疑它可以序列化原始帖子的DataManager,因为它听起来像是有套接字连接和其他类似的类. (3认同)
  • 就像一句警告,我遵循这种技术一段时间,但是你可以作为String传递的内存限制,所以要确保你的数据不是太大. (3认同)

Chr*_*ton 55

弄清楚要采取什么样的路径,不仅要回答CommonsWare关于"为什么"的关键问题,还要回答"为了什么?"的问题.你通过了吗?

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

1)您可以将对象分解为其构成数据,如果另一端知道相同类型的对象,则可以从序列化数据中组装克隆.这就是大多数常见类型通过bundle的方式.

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

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

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


chr*_*ris 20

Parcelable接口是通过将物体与意图的好方法.

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

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

  • 或者它们也可以序列化。 (2认同)
  • +1 @ Mati的注释,但是当应用于单个对象时将其放入上下文10x相当于1 ms.所以也许并不像听起来那么糟糕. (2认同)

Nei*_*eil 14

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

更新:

自定义然后将其添加到AndroidManifest.xml:

<application android:label="@string/app_name" android:debuggable="true" android:name=".CustomApplication"
Run Code Online (Sandbox Code Playgroud)

然后在你的项目中有一个类,如下所示:

package com.example;

import android.app.Application;

public class CustomApplication extends Application {
    public int someVariable = -1;
}
Run Code Online (Sandbox Code Playgroud)

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

CustomApplication application = (CustomApplication)getApplication();
application.someVariable = 123; 
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.

  • 作为一般设计原则,除非你确实需要全局变量,否则最好避免使用全局变量.在这种情况下,有很好的选择. (9认同)

dha*_*g23 11

您还可以使对象Serializable并使用Bundle的getSerializableputSerializable方法.


小智 10

可能的方法:

Bundle bundle = new Bundle();
bundle.putSerializable("key", new CustomObject());
Run Code Online (Sandbox Code Playgroud)

类CustomObject:

class CustomObject implements Serializable{
 private SubCustomObject1 sc1;
 private SubCustomObject2 sc2;
}
Run Code Online (Sandbox Code Playgroud)

子自定义对象:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }
Run Code Online (Sandbox Code Playgroud)


Rup*_*dav 7

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

public class DataBean implements Serializable {
private Date currentTime;

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

public Date getCurrentTime() {
    return currentTime;
 }
}
Run Code Online (Sandbox Code Playgroud)

将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);
}
Run Code Online (Sandbox Code Playgroud)

将对象转换为字节数组

/**
 * 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();
    }
Run Code Online (Sandbox Code Playgroud)

从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();
    }
}
Run Code Online (Sandbox Code Playgroud)

从字节数组中获取对象的方法:

/**
 * 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;
    }
Run Code Online (Sandbox Code Playgroud)

希望这会对其他伙伴有所帮助.

  • 完全不需要所有代码!使用bundle.putSerializable(objectImplementingSerializable) - 这会在你再次在这里重新实现的内容之下...... (3认同)