如何在Android上从一个活动传递对象到另一个活动?

126

我需要能在应用程序的多个活动中使用一个对象,并且它需要是相同的对象。最好的方法是什么?

我已经尝试将对象设置为“public static”,以便其他活动可以访问它,但出于某种原因,这并不能解决问题。还有其他的方法吗?

6个回答

142

当您创建一个意图对象时,可以利用以下两种方法在两个活动之间传递对象。

putParcelable

putSerializable

您可以让您的类实现ParcelableSerializable中的任一接口。然后,您可以在活动之间传递自定义类。我发现这非常有用。

这是我正在使用的一小段代码:

CustomListing currentListing = new CustomListing();
Intent i = new Intent();
Bundle b = new Bundle();
b.putParcelable(Constants.CUSTOM_LISTING, currentListing);
i.putExtras(b);
i.setClass(this, SearchDetailsActivity.class);
startActivity(i);

在新启动的活动中,代码将类似于以下内容...

Bundle b = this.getIntent().getExtras();
if (b != null)
    mCurrentListing = b.getParcelable(Constants.CUSTOM_LISTING);

2
我很久以前就解决了这个问题,但我认为你的答案值得采纳。 - mtmurdock
4
当然,这是我自己的类,不是标准的Android类。我所要说的就是使用一些常量作为密钥! - anargund
6
你在 i.putExtras(b) 中为什么要将一个 Bundle 作为额外的参数,而不直接通过 Intent.putExtra(String name,Parcelable value) 方法将 Parcelable 对象直接放入,并通过 Intent.getParcelableExtra(String name) 方法检索? - Tony Chan
1
我强烈推荐使用Parceler库来处理对象的打包。 - Till - Appviewer.io
如果您使用Android Studio,我建议使用Android Parcelable代码生成器(https://plugins.jetbrains.com/plugin/7332?pr=idea),它允许使用“Generate”上下文菜单实现Parcelable方法。 - Andrei Drynov
显示剩余3条评论

37

你可以创建一个 Application 的子类并将共享对象存储在其中。只要有活动组件存在,应用程序对象就应该在应用程序的生命周期内存在。

从你的活动中,可以通过 getApplication() 访问应用程序对象。


3
好的,这对我来说很新奇。我该怎么实施呢? - mtmurdock
2
@TenFour04 通过在您的清单文件中使用 <application android:name="YourClassName"> 元素进行设置。 - Erich Douglass
2
@TenFour04,这已经是很久以前的事情了,而我的方法也有了很大的改变。我已经找到了很多解决办法。从通过类访问器来访问单例对象,到实现可序列化接口。基本上,我不再试图绕过问题,而是采用了谷歌的方法论。然而,如果所涉及的对象需要存在于应用程序作用域中,@Erich的答案是一个很好的解决方案。 - mtmurdock
我认为这是一个非常糟糕的想法。Application对象及其任何子类不负责保存数据,而仅负责应用程序的基本初始化。使用Preferences、内存缓存(Singleton)、数据库、Realm或其他方式来保存数据,但不要使用子类化的application。 - GabrielWeis
1
我也认为这是一个坏主意,因为当应用程序进程被终止时,Application对象及其所有局部变量都会被销毁。当用户想要从最近的应用程序堆栈中再次打开应用程序时,它会重新创建上次显示的活动。如果此活动依赖于Application对象中以前存储的值,那么由于这些值不再存在,您将遇到问题。有关更多信息,请参阅此博文:不要将数据存储在Application对象中 - BrickTop
显示剩余4条评论

36

本答案特别针对对象具有嵌套类结构的情况。在具有嵌套类结构的情况下,使其可 Parcelable 或 Serializable 有点繁琐。而且,在 Android 上序列化对象的过程不够高效。请考虑以下示例:

class Myclass    {
  int a;
  class SubClass    {
       int b;
  }
}

使用Google的GSON库, 您可以直接将对象解析为JSON格式的字符串,并在使用后将其转换回对象格式。例如:
MyClass src = new MyClass();
Gson gS = new Gson();
String target = gS.toJson(src); // Converts the object to a JSON String

现在,您可以通过活动意图的StringExtra将此字符串作为字符串传递给其他活动。
Intent i = new Intent(FromActivity.this, ToActivity.class);
i.putExtra("MyObjectAsString", target);

然后在接收活动中,从字符串表示中创建原始对象。

String target = getIntent().getStringExtra("MyObjectAsString");
MyClass src = gS.fromJson(target, MyClass.class); // Converts the JSON String to an Object

它可以使原始类保持干净和可重用。最重要的是,如果这些类对象是从 Web 作为 JSON 对象创建的,则该解决方案非常高效且节省时间。

更新


虽然上述方法适用于大多数情况,但出于明显的性能原因,请勿依赖Android捆绑的额外系统来传递对象。有许多解决方案可以使此过程更加灵活和高效,以下是其中几个。每个都有其优缺点。
  1. Eventbus
  2. Otto

这是最好的答案。 - luttu android
2
将对象序列化为GSON格式是否高效?速度快吗? - osrl
1
@osrl 对于普通Java对象(pojos),Gson的速度相当快。虽然建议使用事件总线解决方案。请参考答案中的更新。 - C--
什么是预备数据类型? - Peter Mortensen
@PeterMortensen 不要在意。对不起我的英语。 - C--
这不是最佳答案。最佳答案应该使用 Parcel,因为与序列化相比,它快得多,快得多 - PrashanD

7
也许这个答案不太受欢迎,但在过去,我通常使用一个类,其中包含对我想要在活动之间保留的对象的静态引用。因此,
public class PersonHelper
{
    public static Person person;
}

我曾尝试使用Parcelable接口,但是遇到了一些问题,而且它会增加代码的开销,这让我不太满意。


这是一个很好的解决方案,但并不总是最佳选择。如果您不喜欢Parcelable,并且您的对象可以简化为基本类型(int、float、double、boolean)和字符串,则实现Serializable接口非常容易。几乎不需要您做任何工作,并且开销非常小。 - mtmurdock
1
@mtmurdock:序列化对象是在序列化时的状态的“快照”吗?我需要将一个对象传递给服务,而该服务在运行时会发生变化。该服务应始终使用最新的对象,而不是旧的、准复制的对象。 - stk
1
@stk 是的,序列化对象是一个快照。更准确地说,它是一个副本,这意味着在一个活动中对其进行更改不会影响另一个活动,除非你将其传回。服务是一个很好的选择,但我可以理解为什么有人会觉得这有点过度。另一个解决方案是使用 Android 中内置的持久对象存储保存数据。它可能适合您的需求,如果您需要能够在整个应用程序中获取/设置值,它不是一个坏的解决方案,并且可用于保存持久性数据。 - mtmurdock

6

这取决于您需要访问的数据类型。如果您有一些需要在Activity之间持久存在的数据池,则Erich的答案是正确的选择。如果您只需要从一个活动传递几个对象到另一个活动,则可以让它们实现Serializable并将它们作为Intent的附加项传递给启动新Activity


只要您的对象不需要在应用程序的生命周期内持续存在(这由@Erich Douglas的答案涵盖),这可能是最佳解决方案。 - mtmurdock

6

您的对象还可以实现Parcelable接口。然后,您可以使用Bundle.putParcelable()方法在意图之间传递对象。

Photostream 应用程序使用此方法,并可用作参考。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接