在活动之间共享数据的最佳方式是什么?共享数据而不保存到磁盘将对象保存到磁盘

2022-08-31 05:32:16

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

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

但是,我想分享很多变量,有些可能相当大,所以我不想像上面那样创建它们的副本。

有没有办法在不使用 get 和 set 方法的情况下直接获取和更改变量?我记得在Google开发网站上读过一篇文章,说不建议这样做,以便在Android上实现性能。


答案 1

以下是实现此目的的最常见方法的汇编:

  • 在意向内发送数据
  • 静态字段
  • 哈希映射WeakReferences
  • 持久化对象(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

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

共享数据而不保存到磁盘

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

注意:有时,当用户离开您的活动(未退出)时,Android 可能会决定终止您的应用程序。在这种情况下,我遇到过这样的情况,即Android尝试使用应用程序被杀死之前提供的意图启动最后一个活动。在这种情况下,存储在单例(您的或)中的数据将消失,并且可能会发生不好的事情。为避免这种情况,您可以将对象保存到磁盘,或者在使用数据之前检查数据以确保其有效。Application

使用单例类

有一个类来保存数据:

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.ApplicationApplication

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

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

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。这完全取决于您的具体问题。

将对象保存到磁盘

这个想法是在启动其他活动之前将数据保存在磁盘中。

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

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

保留对象的一些方法包括:


答案 2

您可以使用什么:

  1. 在活动之间传递数据(如克里斯蒂安说)
  2. 使用具有大量静态变量的类(因此,您可以在没有类的实例的情况下调用它们,而无需使用 getter/setter)
  3. 使用数据库
  4. 共享首选项

您的选择取决于您的需求。当你有“很多”时,你可能会使用多种方式


推荐