【问题标题】:How do I preserve data objects in Android/Java?如何在 Android/Java 中保存数据对象?
【发布时间】:2013-07-15 18:20:17
【问题描述】:

我是一名电脑爱好者,正在开发一款适用于 Android 平台的小型问答游戏。

在这个游戏中,我在多个活动/视图页面(条目、问题页面、答案页面、最终得分页面)之间移动玩家。我创建了一个问题对象,其中包含与单个琐事问题相关的所有数据(问题、四个答案、指向正确答案的指针、计算机在响应玩家猜测时生成的相关 cmets),并且我已经成功填充了一个 ArrayList包含我从 XML 文件 DOM 解析的数据的 Question 对象。

随着游戏的进行,在活动之间来回传递这些数据的可接受方式是什么?当用户在游戏中移动时,如何让这些数据对象保持活跃?

我了解非常不鼓励使用全局变量。我还了解到单例设计模式带来了许多据说与全局变量相关的问题。在寻找这些方法的替代品时,我感到很困惑。

我了解 MVC 方法的基础知识。我的活动 *.java 文件是控制器文件,它们链接到我使用 XML 创建的布局(视图)。我有两个“模型”对象需要随着游戏的进行而维护和修改:(1)上面提到的问题库 ArrayList 和(2)某种“PlayerProgress”对象,其中包含与玩家进度相关的所有数据游戏。

这些数据对象在游戏开始时首先被实例化,但我不知道如何在用户在活动之间移动时让它们保持活动状态。我知道我可以在活动之间以 EXTRAS 的形式传递信息,但 EXTRA 似乎不是为此目的而设计的。即使 EXTRAS 为玩家进度属性工作,我认为我不能使用它们在活动之间传递 25-50 个问题对象的 ArrayList。

我已经研究过序列化和可打包,但是每次用户在不同的活动/视图之间来回移动时,基本上分解然后重新组合我的数据模型对象似乎很奇怪(并且可能效率低下)。如果其中一个是可以接受/常见的方式来实现这一点,我可以很高兴地向前推进,但我想先与其他人核实。

我一直在用不同的编程语言对此表示反对,并怀疑我无法理解图片中更大的部分。我已经阅读了许多不同资源中对对象和应用程序生命周期的描述,但我仍然没有设法找出这个基本问题的解决方案。

我在我愚蠢的琐事游戏的背景下问这个问题(“随着游戏的进行,在活动之间来回传递数据对象的可接受方式是什么”),但我真的很关心如何处理在更大的图景上。如果人们没有时间拼出一些看似基本的东西,也许您可​​以向我指出您认为有用的其他书籍中的描述? (我的 Safari 书架上有几个空位,可以找到几乎所有技术出版物的副本。)

谢谢。

【问题讨论】:

  • "我认为我不能使用它们在活动之间传递 25-50 个问题对象的 ArrayList。" - 你绝对可以,实际上
  • invertigo,我的印象是 EXTRAS 是键/值对,其值通常是 String 或 int 数据类型。如果单个 EXTRA 值可以包含 25-50 个问题对象的整个 ArrayList,那似乎很理想。我现在正在进一步研究,以确保我没有完全误解我们可以用 extras 做什么。
  • 您必须评估对您自己的用例的性能影响,但我一直使用可序列化的额外对象来存储可序列化对象的列表
  • 我会这样做的。我完全不知道序列化对象的成本有多大。在抽象的层面上,它似乎可能很昂贵,但是——如果 CPU 能够达到 13,800 MIPS,我想序列化一个小小的琐事问题库不会有什么大不了的。

标签: java android model-view-controller


【解决方案1】:

我没有足够的票数直接在 323go 的帖子中回答关于静态变量的问题……但那个实现完全是单例。我想指出这一点,因为您在问题中指出,您还了解到 Singleton 设计模式带来了许多据说与全局变量相关的问题

我承认,如果您习惯于调用具有内联参数的函数或程序,那么第一次使用附加功能会很奇怪,但这似乎是 Android 中的常用方式。 我看不出使用附加功能有什么问题,因为如果您的模型对象不是很复杂,它对您来说几乎是透明的。我的意思是你只需要实现“Serializable”接口就可以了。有些数据类型不能“单独”使用 Serializable(作为列表)工作,您需要实现 Parcelable,但您可以声明数组 insted。 Parcelable 似乎“效率更高”,所以如果你想要更好的表现,你无论如何都需要实现 Parcelable,就像这里有人说的那样: Android: Difference between Parcelable and Serializable?

我不认为 Shared Preferences 旨在用作“传递参数工具”,因为它不会那么高效,因为它必须写入和读取物理内存,什么是“艰苦的工作”任何计算机系统;而 exras 将通过内存堆栈发送(免责声明:我没有测试,但这是逻辑告诉我的)。我使用 dannyroa 的方式(存储 json 对象)来解决诸如用户偏好、互联网检索到几乎没有更新的数据、得分、保存游戏等长期存在的问题。

最后……也许你可以重构你的代码。您是否为每个问题打开一个新活动?也许您可以只使用一个 Activity 并使用片段。然后,您可以在活动中拥有全局变量,并且内部的任何片段都可以使用 getActivity() 访问那里。

((MyActivity)getActivity()).myGlobalVariable();

【讨论】:

  • 谢谢,安德。我发现全局静态对象正是 Singleton。我只使用 PREFERENCES 来存储关于用户整体地位的真正持久信息的一两位。我正在通过您的链接挖掘可打包、可序列化的内容。我显然需要更好地处理 EXTRAS。 // 我现在只有一个问题活动,并且正在使用视图翻转器在问题和结果之间来回跳跃。这解决了促使原始帖子出现的大部分问题。片段建议似乎是一个类似的解决方案。谢谢!
  • 嗨,安德,只是想跟进并确认您建议我应该使用片段的智慧。我正在用片段重新编写游戏的第二个版本,它完全解决了我的问题,正是你提到的原因。
【解决方案2】:

您可以在 Intent Extras 中放置一组可打包的对象,这样就可以在活动之间发送一组可打包的问题对象。

我个人会使用 sqlite 数据库来存储问题并通过内容提供程序从数据库中提取它们。

对于您当前的应用程序来说可能是多余的,但如果您扩展问题集,您可以更改 SQL 以提取每个活动的相关问题子集。

【讨论】:

  • 谢谢,jsr。我将尝试这种方法。
【解决方案3】:

我尝试将它们保存在 SharedPreferences 中。

为了保存对象,我使用 Gson 库将其转换为 JSON 字符串并将 JSON 字符串转换回对象。

但是,这意味着它仅适用于 Serializable 对象,并且从 SharedPreferences 读取和写入会产生开销。

理想的解决方案是全局静态和 SharedPreferences 的组合。如果静态变量为空,请从 SharedPreferences 中获取。确保在 SharedPreferences 中的值更新时清除静态变量。

static String userInfo = null;
public static String getUserInfo() {
    if (userInfo != null) {
        return userInfo;
    }
    return _getStringFromPref("userInfo");
}

public static String setUserInfo(String val) {
    _putStringToPref("userInfo", val);
    userInfo = val; //or you can just set userInfo to null;
}

您也可以使用本地数据库 (sqlite) 代替 SharedPreferences。

【讨论】:

  • 谢谢,丹尼罗亚。我将尝试“静态全局”方法。将在 cmets 部分进行更新。
  • Aaron:我尝试过静态全局,但问题是当您的应用程序进入后台时,您不能保证该值会在那里。如果 Android 需要释放内存,它们会在后台清理分配给应用的内存。
  • 嗯。我明白你在说什么,丹尼罗亚。如果我将这两种解决方案结合起来会怎样?我想知道是否可以覆盖与移动到后台的应用程序关联的方法。在那些时候,我会使用 GSON 库将其转换为 JSON 字符串。否则,当只是在活动之间来回移动时,我会使用静态全局。 // 但这只有在我能确定我总是能及时捕捉到事件的情况下才有效。
  • 我个人使用全局静态和 SharedPreferences 的组合。请参阅我的更新答案。
【解决方案4】:

在我原来的帖子中,我承诺会在调查完所有选项后回过头来。

只是想报告一下,正如 Ender 所建议的,最简单的解决方案是使用多个片段和一个活动页面。这使得完全避免全局静态对象成为可能,因为所有片段都可以访问 MainActivity 类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    相关资源
    最近更新 更多