26

我有一个包含一些静态变量的应用程序。这些变量存储在一个名为 DataContext 的独立类中。这些变量在应用程序启动时从原始文件初始化(在扩展 Application 的 MyApplication 的 onCreate() 中调用名为 DataContext.initConstant() 的方法)。

(编辑:initConstant 方法使用 AsyncTask 从文件中加载此数据)。

当我的应用程序进入后台一段时间或当我的应用程序使用大量内存时,这些静态变量变为空。

  1. 如何预防?

  2. 如果不是,我应该如何处理我的静态变量?

    我有其他数据存储在静态变量中以在不同的活动中使用,但我清除它们或将它们传递给onLowMemory()MyApplication 中的 null。

  3. 如果这些数据太大而无法在 Intent 中序列化、无法使用数据库(无论出于何种原因)并且也无法通过序列化存储在文件中,那么保持活动之间可访问的一些数据的最佳方法是什么?

4

7 回答 7

5
  1. 你不能。Android 需要不时释放内存。想象一下,如果所有应用程序都有大量应该永久驻留的静态数据 - 您将如何将其放入内存中?这是一部手机。它没有虚拟内存。

  2. (和 3):任何打算持久化的东西都需要通过 SharedPreferences、Sqlite 数据库或文件来存储。

于 2011-01-25T18:10:51.113 回答
5

最有可能的问题是您的应用程序在后台被杀死,然后在您返回时重新创建。查看Activity Lifecycle文档,了解单个活动何时可能发生这种情况。您需要确保在正确的时间点将内存中存储的任何内容移动到更永久的存储空间,以避免在应用程序被终止时丢失该信息。

我不确定您到底存储了什么,但听起来使用共享首选项可能效果很好。这个关于数据存储的页面解释了一些更永久地存储数据的不同方法,包括共享首选项。

于 2011-01-25T18:13:02.457 回答
2

如果您没有使用原始文件,我建议在加载类时进行初始化。

例如,

public static Map<?,?> myStaticMap = new HashMap<?,?>();
static { //fill myStaticMap }

如果您以这种方式加载文件,您确实需要担心一些更大的问题。例如,I/O 错误或延迟问题呢?您将在姜饼(如果您启用它们)中收到警告,以便在您的主线程中执行 I/O。也许您应该有一个对象来检索这些值,而不是一个具有静态字段的类。(也许使用静态缓存,尽管您应该在检查/更改之前对其进行同步)

于 2011-01-25T18:29:06.740 回答
2

我认为这是一个数据缓存问题。

当用户经常交换应用程序时,不能保证在静态类中存储数据。Android 系统会在内存不足时回收所有后台活动。静态类绝对属于这一类。

正确的做法是使用sharedPreference来持久化缓存数据。

您可以创建自己的 getter 和 setter 所需的数据,并将其包装在 sharedPreference 对象周围。使用 getter 访问时,应始终检查该值是否为空或过期。update_time您可以在使用 setter 时存储一个。

对于特定于活动的数据,您可以使用getPreference(permission),如果您想在活动和其他应用程序组件之间共享数据,您可以使用getSharedPreference(name, permission).

通常,权限将为 MODE_PRIVATE ,这样数据只能在您的应用程序中访问。

您应该将数据分组并存储在不同的 sharedPreference 对象中。这是一种很好的做法,因为当您想要使该组数据无效时,只需一个班轮即可。

editor.clear(); editor.commit()

如果要缓存复杂对象,则应将其序列化。我更喜欢 JSON 格式。所以你需要一些转换机制。为此,我将创建扩展 JSONable 类的数据对象类。JSONable 类将具有toJSON()方法和readFromJSON(). 这在恢复和序列化数据时很方便。

于 2013-03-27T11:58:03.847 回答
1

我将一个User对象和一个Client对象存储在我的静态范围内。我不时注意到引用变为空。所以现在在我的吸气剂中,我检查这个值是否为空,如果是,我重新启动应用程序。

Intent i = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                context.startActivity(i);

我也可以选择重新加载客户端,因为我将访问令牌存储在 prefs 中,但是我做了很多初始化,所以我决定重新启动应用程序是最好的主意。

于 2011-01-25T18:19:02.207 回答
1

在您的onResume()方法中,您可以查询静态数据以查看它是否存在,如果不存在,请重新加载。

于 2012-08-28T13:15:14.453 回答
0

您可以使用共享首选项来存储值,而不是使用静态变量。

注意:对于共享偏好,您也不应该给予沉重的负担。

我已经通过使用带有 getter 和 setter 函数的超类来存储和检索共享首选项变量来解决这个问题。

我的应用程序中的所有类都扩展了超类而不是活动。

于 2012-01-19T05:38:56.413 回答