【问题标题】:Saving cursor state with activity instance?使用活动实例保存光标状态?
【发布时间】:2010-04-27 20:07:50
【问题描述】:

我有一个 android 应用程序,它从 SQLite 数据库中随机抽取 20 个问题(行)作为光标,并循环遍历所有问题以询问用户所有 20 个问题。

有没有办法在 Activity 暂停或停止时保存光标的状态/位置,以便在 Activity 恢复时将光标恢复到与 Activity 暂停/停止时相同的位置?

如果您需要我发布我的代码,请询问。

感谢您的宝贵时间!

【问题讨论】:

    标签: android cursor cursor-position savestate


    【解决方案1】:

    让它保存它所在的位置很容易,只需在 onPause 方法中添加一些代码,如下所示:

    protected void onPause(){
     position = yourCursor.getPosition();
     super.onPause();
    }
    

    其中位置是一个类字段(即在任何方法之外声明,通常在顶部)。然后在 onResume 中,您只需将光标移回该位置即可。如果您不熟悉 onPause()/onResume(),请阅读 activity lifecycle。但是,我怀疑您还想保存随机选择的问题。我认为您的光标不会在 onPause/onResume 中持续存在,因为它们通常在 onPause 中关闭以避免内存问题。我唯一能想到的(但我不是专家)是您必须保存问题的 rowID,然后重新查询数据库以获取这些行。该解决方案的笨拙程度首先取决于您如何查询随机问题。如果您已经生成了 20 个随机数,然后将其输入到查询中,那么您可以重复使用相同的方法,但使用已保存的 20 行来代替。


    这太长了,不适合作为评论:

    @Ryan:确实,如果您无法重新创建相同的光标,那么在没有光标状态的情况下保存位置是毫无用处的——这就是我在回复的后半部分所说的。我假设您的 RANDOM() 是标准 SQL 函数? (顺便说一句,Android 中的语法是什么?我无法让我的数据库接受它。)如果是这样,那么您可能必须使用蛮力方法来重新创建光标。我的意思是用“rowId = ? OR rowId = ? OR rowId = ? OR....”重新查询数据库,选择参数是您从原始游标中检索到的 rowIds。它不漂亮,可能有更好的方法来做到这一点,但这会奏效。使用这样的循环构建 SELECT 字符串会很容易:

    String selectQuery = "";
    String[] selectArgs = new String[savedRows.length];
    for (int i = 0; i < savedRows.length; i++){
        selectQuery = selectQuery.concat("rowID = ? OR ");
        selectArgs[i] = Long.toString(savedRows[i]);
    }
    
    //Remove the last " OR " you'd have in the string
    int index = selectQuery.lastIndexOf(" OR ");
    selectQuery = selectQuery.substring(0, index);
    

    这是假设您在 onPause 方法中将原始光标中的 rowIds 保存到 long[] savedRows 中。然后,您可以将它们传递到新的数据库查询中。


    同样,对于 cmets 来说太长了:

    @Ryan:很好,他们可能不会以相同的顺序被拉回。你可以尝试看看,但很难说它总是以相同的顺序返回是侥幸还是设计使然。好的,想法 3 正在创建一个中间表,其中填充了 20 个随机问题。该表将有一列作为其行号(为您提供问题的顺序),然​​后是一个外键列,其中包含问题表中问题的 rowId。从该表中以相同顺序检索您的问题很容易,一旦用户完成所有问题,您就可以删除该表。或者,您甚至可以保留表格,以便用户可以看到他们在过去的问题集上的表现 - 但这是一个完全不同的功能。

    注意:我应该在我的第一篇文章中也提到 onSaveInstanceState。 onPause 是在更改活动之前进行快速保存的好地方,但简单地将位置保存到 int 中并不是万无一失的。显然,当用户开始一个新的测验时它会重置(因为它应该),但是如果当用户正在查看另一个活动时,它也会重置,操作系统必须终止你的进程以获取内存。在这种情况下,当用户返回活动时,它必须从 onCreate 重新启动,因此它会丢失可变数据。这旨在与 onSaveInstanceState() 方法一起使用,该方法为您提供了一个可以将数据保存到其中的 Bundle。然后在 onCreate 中提供相同的 Bundle,允许您重新加载任何必要的内容,并使其看起来像应用程序从未被杀死。

    【讨论】:

    • @Steve H:感谢您的回复。我实际上是使用接受限制参数的 SQLiteDatabase 类的查询方法填充游标。我将 RANDOM() 传递给参数的顺序,将 20 传递给限制参数。我不确定在不存储游标的实际行顺序的情况下存储游标位置是否会对我有好处。因此我需要保存光标本身的状态。
    • @Steve H:是的,RANDOM() 作为 SQLite 数据库中的标准函数工作。试试这个查询“SELECT * FROM SOME_TABLE ORDER BY RANDOM()”。我确实明白你在说什么,但如果行没有按照原始光标拉动它们的确切顺序返回,我认为你所说的在这种情况下不会有帮助吗?我提出了 20 个随机问题,然后活动在第 5 个问题上暂停/停止。当我恢复活动并再次拉动行时,这些行是否会以与最初使用上述方法时完全相同的顺序被拉动?
    • @Steve H:我真的很喜欢临时表的想法。但是我想我应该提到我只关心在手机方向改变时保存光标的状态。我发现了另一篇关于堆栈溢出的帖子,该帖子使用 onRetainNonConfigurationInstance() 进行了引用,这对于我需要的东西来说就像一个梦想,尽管我最终可能会调整我的应用程序以使用你的临时表想法。感谢您的帮助!
    猜你喜欢
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多