Android:内存不足时静态变量null

时间:2011-01-25 18:06:44

标签: android memory static low-memory

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

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

当我的应用程序在后台运行一段时间或者我的应用程序用于大量内存时,这些静态变量将变为空。

  1. 如何预防?

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

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

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

7 个答案:

答案 0 :(得分:5)

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

我不确定你究竟存储了什么,但听起来好像使用共享首选项可能效果很好。 Data Storage上的这个页面解释了一些更永久存储数据的不同方法,包括共享首选项。

答案 1 :(得分:4)

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

  2. (和3):任何旨在持久的东西都需要通过SharedPreferences,Sqlite数据库或文件进行存储。

答案 2 :(得分:2)

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

例如,

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

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

答案 3 :(得分:2)

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

当用户经常交换应用程序时,无法保证在静态类中存储数据。当内存不足时,Android系统将回收任何后台活动。静态类肯定属于这一类。

正确的方法是使用sharedPreference来保留缓存数据。

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

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

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

您应该将数据分组并存储在差异的sharedPreference对象中。这是一种很好的做法,因为当你想要使这组数据无效时,这只是一个问题。

editor.clear(); editor.commit()

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

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:1)

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

答案 6 :(得分:0)

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

注意:对于共享偏好,您也不应给予重负荷。

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

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