【问题标题】:Best method for saving data - preferences, sqlite, serializable or other?保存数据的最佳方法 - 首选项、sqlite、可序列化或其他?
【发布时间】:2011-02-10 20:41:21
【问题描述】:

我一直在研究在回合之间保存游戏数据的替代方法,想知道是否有人能指出正确的方向。

我有大约 32k 的数据必须在 onPause 期间保存。由于数据量巨大,我排除了偏好。我花了几天时间使用 SQLite,但无法在不到两秒的时间内保存数据(尽管时间肯定没有被浪费)。

我决定在游戏开始时使用数据库来加载常量数据。这肯定会更容易调整游戏中的各种参数和默认值。但这仍然让我寻找写入数据的理想方法。

需要保存的数据基本上是 9 次出现的 A 类和 9 次出现的 B 类。我在 Android 的学习曲线(以及 Java 的细微差别,来自 C++ 背景)和一直在疯狂地搜索。这让我想到了两种可能性 -

1)序列化(ObjectOutputStream)

我认为这将是一个完美的解决方案,但在阅读了有关该主题的其他几篇文章后,我认为在 Android 平台上不强烈推荐它,因为速度和内存分配会引发垃圾收集器的潜在愤怒。

2) DataOutputStream 类

我目前的想法是在两个类中添加 Load 和 Save 函数,并在它们中使用 DataOutputStream 和 DataInputStream 调用来分别写入和读取数据。

类中的数据是基元(主要是字符串和整数)和基元数组,所以没有什么太复杂的东西可以分解。这第二种解决方案看起来不错,可行吗?或者还有其他我不知道的解决方案吗?

【问题讨论】:

  • 要考虑的主要考虑因素是写入闪存可能是一个很长的操作,与数据大小无关。即使写入 1 个字节也可能需要相当长的时间。因此,请确保您的解决方案缓冲所有数据并以尽可能少的操作写入数据。
  • 感谢您的建议。我已经使用了 DataOutputStream 方法,现在写入数据的时间可以忽略不计(大约 0.1 秒)。不过,我很高兴我对 SQLite 数据库有所兴趣,因为它们肯定也会非常有用:)

标签: android file


【解决方案1】:

你应该使用异步任务来保存数据,我使用这种方法在开始游戏时获取高分:

new HighscoreTask().execute(this);

异步任务如下所示:

public class HighscoreTask extends AsyncTask<MainView, Void, Void> {

    protected void onPreExecute() {
    }

    protected void onPostExecute(final Void unused) {
    }
    @Override
    protected Void doInBackground(MainView... params) {
        HighScoreFactory.syncScores();
        return null;
    }
}

所有的数据库交互都发生在 HighScoreFactory.syncScores() 中,因为它发生在后台,所以只要需要就可以。在我的例子中,它向外部服务器发送一个 HTTP 请求并将这些请求加载到数据库中。它从来没有引起任何问题并且可以无缝运行。

【讨论】:

  • 谢谢 - 我一定会记住这一点。我现在将游戏数据保存为原始二进制文件,它的工作速度要快 很多。但肯定会像现在一些人建议的那样研究 Async。
【解决方案2】:

为什么你的数据库写入有 2 秒的限制?如果纯粹是为了 UI 响应,那么您可以采取另一种方法。

您实际上不必在您的onPause 方法本身中执行保存,您可以启动一个新的Thread,它实际上会为您保存。

private void backgroundSave(){
    Thread backgroundThread = new Thread() {
        @Override
        public void run() {
            //do save here
        }
    };
    backgroundThread.start();
}

@Override
protected void onPause() {
    super.onPause();
    backgroundSave();
}

您也可以为此使用AsyncTask

您可能需要考虑用户在保存完成之前尝试重新启动您的应用的情况,但这应该不难考虑。

【讨论】:

  • 正在保存的数据在所有活动中都会不断使用。将保存分配给后台线程的想法听起来不错,但我还没有时间熟悉解决同步问题。一旦有机会,我肯定会尽快研究。目前,我发现我可以在大约 0.1 秒内将数据写入二进制文件。不过我很感激这个建议。要学的东西太多了,时间太少了...... :)
【解决方案3】:

您是否尝试过在事务中向数据库中插入数据?

try{
 db.beginTransaction();

 //here insert data to database    

 db.setTransactionSuccessful();
} finally {
 db.endTranscation();
}

这样可以加快运行速度。

【讨论】:

  • 我尝试使用事务,直到我的所有写入都在一个事务中完成 - 这将时间从 8 秒缩短到 2 秒。在那一点上,我似乎撞到了一堵砖墙,甚至十分之一秒,都不能再低了。这是我完成的第一个 SQLite 编码,但我的感觉是我无法更快地得到它(尽管我很高兴被告知否则)
【解决方案4】:

创建一个新的线程,使用 Context.openFileOutput(String name, int mode) 以 this 作为上下文进行数据写入。然后,您可以使用新线程在后台编写它并使用以下命令检索它: Context.openFileInput(String name) 再次使用 this 作为上下文。希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-09
    • 2013-01-08
    • 2015-09-15
    • 2013-01-29
    • 1970-01-01
    • 2012-05-23
    • 2015-08-03
    • 2017-12-11
    相关资源
    最近更新 更多