我有一个活动,它是整个应用程序中使用的主要活动,它有许多变量。我有另外两个活动,我希望能够使用来自第一个活动的数据。 现在我知道我可以这样做:

GlobalState gs = (GlobalState) getApplication();
String s = gs.getTestMe();

然而,我想要分享很多变量,其中一些可能相当大,所以我不想像上面那样创建它们的副本。

是否有一种方法可以直接获取和更改变量而不使用get和set方法?我记得在谷歌开发网站上读过一篇文章,说不建议在Android上使用这种性能。


我有一些想法,但我不知道它们是否是你想要的。

您可以使用一个保存所有数据的服务,然后将活动绑定到该服务以进行数据检索。

或者将您的数据打包为可序列化或可打包的,并将它们附加到一个bundle中,并在活动之间传递该bundle。

这可能根本不是你要找的,但你也可以尝试使用SharedPreferences或一般的首选项。

不管怎样,让我知道你的决定。


以下是实现这一目标最常见的方法:

在意图内发送数据 静态字段 WeakReferences的HashMap 持久化对象(sqlite、共享首选项、文件等)

TL;DR:共享数据有两种方式:在意图的附加中传递数据或将数据保存在其他地方。如果数据是原语、字符串或用户定义的对象:将其作为意图附加的一部分发送(用户定义的对象必须实现Parcelable)。如果传递复杂对象,则将实例保存在其他地方的单例中,并从启动的活动中访问它们。

一些如何以及为什么实现每种方法的例子:

在意图内发送数据

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("some_key", value);
intent.putExtra("some_other_key", "a value");
startActivity(intent);

关于第二个活动:

Bundle bundle = getIntent().getExtras();
int value = bundle.getInt("some_key");
String value2 = bundle.getString("some_other_key");

如果要传递基元数据或字符串,请使用此方法。您还可以传递实现Serializable的对象。

虽然很诱人,但在使用Serializable之前应该三思:它很容易出错,而且非常慢。所以一般来说:如果可能的话,远离Serializable。如果您想传递复杂的用户定义对象,请查看Parcelable接口。它更难实现,但与Serializable相比,它有相当大的速度提升。

共享数据而不持久化到磁盘

在大多数情况下,两个活动都运行在同一个进程中,因此可以通过将数据保存在内存中来在活动之间共享数据。

注意:有时候,当用户离开你的activity时(没有退出),Android可能会决定终止你的应用程序。在这种情况下,我有经验的情况下,android试图启动最后一个活动使用的意图提供之前的应用程序被杀死。在这种情况下,存储在单例(您的或应用程序)中的数据将消失,可能会发生糟糕的事情。为了避免这种情况,要么将对象持久化到磁盘,要么在使用数据之前检查数据以确保其有效。

使用单例类

有一个类来保存数据:

public class DataHolder {
  private String data;
  public String getData() {return data;}
  public void setData(String data) {this.data = data;}

  private static final DataHolder holder = new DataHolder();
  public static DataHolder getInstance() {return holder;}
}

从启动的活动:

String data = DataHolder.getInstance().getData();

使用单例应用程序

应用单例是android.app.Application的一个实例,它是在应用启动时创建的。你可以通过扩展Application来提供一个自定义的:

import android.app.Application;
public class MyApplication extends Application {
  private String data;
  public String getData() {return data;}
  public void setData(String data) {this.data = data;}
}

活动开始前:

MyApplication app = (MyApplication) getApplicationContext();
app.setData(someData);

然后,从启动的活动中:

MyApplication app = (MyApplication) getApplicationContext();
String data = app.getData();

静态字段

其思想基本上与单例相同,但在这种情况下,你提供了对数据的静态访问:

public class DataHolder {
  private static String data;
  public static String getData() {return data;}
  public static void setData(String data) {DataHolder.data = data;}
}

从启动的活动:

String data = DataHolder.getData();

WeakReferences的HashMap

同样的想法,但是允许垃圾收集器删除未引用的对象(例如当用户退出活动时):

public class DataHolder {
  Map<String, WeakReference<Object>> data = new HashMap<String, WeakReference<Object>>();

  void save(String id, Object object) {
    data.put(id, new WeakReference<Object>(object));
  }

  Object retrieve(String id) {
    WeakReference<Object> objectWeakReference = data.get(id);
    return objectWeakReference.get();
  }
}

活动开始前:

DataHolder.getInstance().save(someId, someObject);

从启动的活动:

DataHolder.getInstance().retrieve(someId);

你可能需要也可能不需要使用意图的附加来传递对象id。这完全取决于你的具体问题。

将对象持久化到磁盘

其思想是在启动其他活动之前将数据保存到磁盘中。

优点:您可以从其他地方启动活动,如果数据已经被持久化,那么它应该可以正常工作。

缺点:它很麻烦,需要更多的时间来实现。需要更多的代码,因此更有可能引入错误。它也会慢得多。

持久化对象的一些方法包括:

将它们保存到共享首选项 将它们保存到sqlite数据库中 将它们保存到一个文件中(我会避免这个文件)


假设你使用Intent从活动一调用活动二。 你可以通过intent.putExtra()传递数据,

拿着这个作为你的参考。 使用Intent.putExtra发送数组

希望这是你想要的。


如果你的意图是从当前Activity调用其他Activity,你应该使用intent。您可以将重点放在按需共享数据而不是持久化数据上。

However, if you really need to persist these values then you could persist them in some kind of structured text file or database on local storage. A properties file, XML file, or JSON file could store your data and be easily parsed during activity creation. Don't forget also that you have SQLite on all Android devices, so you could store them in a database table. You could also use a Map to store key-value pairs and serialize the map to local storage, but this might be too cumbersome to be useful for simple data structures.


你可以用什么:

在活动之间传递数据(如Cristian所说) 使用带有大量静态变量的类(这样就可以在不使用类实例和getter/setter的情况下调用它们) 使用数据库 共同的喜好

你选择什么取决于你的需要。当你使用"a lot of"时,你可能会使用不止一种方式


“然而,我想分享很多 变量,有些可能是 很大,所以我不想创造 像上面这样的副本。”

这并不会产生复制(特别是对于String,但即使对象也是通过引用的值传递的,而不是对象本身,像这样的getter是可以使用的——可以说比其他方法更好使用,因为它们是常见的和易于理解的)。旧的“性能神话”,比如不使用getter和setter,仍然有一些价值,但也在文档中更新了。

但如果你不想那样做,你也可以让变量在GlobalState中为public或protected,然后直接访问它们。并且,你可以创建一个静态单例,就像Application对象JavaDoc指出的那样:

通常不需要子类化 应用程序。在大多数情况下, 静态单例也可以提供同样的功能 以更模块化的方式实现功能。 如果你的单例需要全局 上下文(例如注册 广播接收机),功能到 检索时可以给它一个Context 内部使用 Context.getApplicationContext()时 首先构造单例。

使用Intent数据是传递数据的另一种方式,但它通常用于较小的数据和简单类型。您可以传递更大/更复杂的数据,但这比使用静态单leon更复杂。不过,Application对象仍然是我个人最喜欢的在Android应用程序组件之间共享更大/更复杂的非持久性数据的对象(因为它在Android应用程序中有一个定义良好的生命周期)。

另外,正如其他人所注意到的,如果数据变得非常复杂并且需要持久化,那么您也可以使用SQLite或文件系统。


你可以扩展Application类并标记任何你想要的对象,然后它们就可以在你的应用程序的任何地方使用


做谷歌命令你做的事!: http://developer.android.com/resources/faq/framework.html # 3

基本数据类型 非持久化对象 单例类-我最喜欢的:D 一个公共静态字段/方法 对象弱引用的HashMap 持久对象(应用程序首选项,文件,内容提供程序,SQLite DB)


All of the aforementioned answers are great... I'm just adding one no one had mentioned yet about persisting data through activities and that is to use the built in android SQLite database to persist relevant data... In fact you can place your databaseHelper in the application state and call it as needed throughout the activates.. Or just make a helper class and make the DB calls when needed... Just adding another layer for you to consider... But all of the other answers would suffice as well.. Really just preference


Using the hashmap of weak reference approach, described above, and in http://developer.android.com/guide/faq/framework.html seems problematic to me. How are entire entries reclaimed, not just the map value? What scope do you allocate it in? As the framework is in control of the Activity lifecycle, having one of the participating Activities own it risks runtime errors when the owner is destroyed in advance of its clients. If the Application owns it, some Activity must explicitly remove the entry to avoid the hashmap from holding on to entries with a valid key and a potentially garbaged collected weak reference. Furthermore, what should a client do when the value returned for a key is null?

在我看来,由应用程序拥有或在单例中拥有WeakHashMap是更好的选择。映射中的值是通过键对象访问的,当不存在对键的强引用时(即所有活动都使用键及其映射到的对象完成),GC可以回收映射条目。


在活动之间共享数据 使用实例登录后传递邮件

“email”是可以用来引用正在请求的活动的值的名称

1登录界面代码

Intent openLoginActivity = new Intent(getBaseContext(), Home.class);
    openLoginActivity.putExtra("email", getEmail);

主页上的2个代码

Bundle extras = getIntent().getExtras();
    accountEmail = extras.getString("email");

如果你想处理数据对象,这两个实现非常重要

Serializable和Parcelable

Serializable is a marker interface, which implies the user cannot marshal the data according to their requirements. So when object implements Serializable Java will automatically serialize it. Parcelable is android own serialization protocol. In Parcelable, developers write custom code for marshaling and unmarshaling. So it creates less garbage objects in comparison to Serialization The performance of Parcelable is very high when comparing to Serializable because of its custom implementation It is highly recommended to use Parcelable implantation when serializing objects in android.

公共类User实现了Parcelable

点击这里查看更多信息


在活动之间共享数据有多种方式

1:使用Intent在活动之间传递数据

Intent intent=new Intent(this, desirableActivity.class);
intent.putExtra("KEY", "Value");
startActivity(intent)

2:使用静态关键字,将变量定义为公共静态,并在项目中使用任何位置

      public static int sInitialValue=0;

在项目的任何地方使用classname.variableName;

3:使用数据库

但其过程较长,插入数据时必须使用查询,需要时使用游标迭代数据。但是如果不清理缓存就不会丢失数据。

4:使用共享首选项

比数据库简单多了。但是有一些限制,你不能保存ArrayList,List和自定义对象。

5:在application类中创建getter setter,并访问项目中的任何地方。

      private String data;
      public String getData() {
          return data;
      }

      public void setData(String data) {
          this.data = data;
      }

这里设置和获取活动

         ((YourApplicationClass)getApplicationContext()).setData("abc"); 

         String data=((YourApplicationClass)getApplicationContext()).getData();  

有一种新的更好的方式可以在活动之间共享数据,它就是LiveData。特别要注意Android开发者页面上的这句话:

LiveData对象能够感知生命周期这一事实意味着您可以在多个活动、片段和服务之间共享它们。为了保持示例简单,可以将LiveData类实现为单例

这样做的意义是巨大的——任何模型数据都可以在LiveData包装器中的公共单例类中共享。为了可测试性,它可以从活动中注入到各自的ViewModel中。并且您不再需要担心弱引用来防止内存泄漏。