SQL 游标在调用 getString 时抛出内存不足

And*_*oid 5 android out-of-memory xml-deserialization sqlcipher

对我之前问题的附件参考:-内存不足

我会尽量准确。我从我的网络服务调用一个长 base64 字符串得到响应。我解码字符串并得到一个包含我的数据的巨大字符串。我反序列化字符串并使用如下字符串创建我的类的对象。

String decryptedXml = XmlObject.toDecryptedXmlString(gameDetail.getGameData(), app.getSessionEncryptionKey());
Game noviceGame = deserialiseGame(decryptedXml, NoviceGamer.class);
Run Code Online (Sandbox Code Playgroud)

desrialiseGame() 只是一种反序列化数据并创建并返回我的游戏实例的方法。为了将这个对象维护到多个会话(登录/注销),我将整个游戏数据(我的反序列化给了我游戏实例的字符串)存储在数据库中。

下次当用户登录时,为了创建游戏实例,我从我的数据库中获取字符串并再次尝试反序列化,以便我取回我的游戏实例。但是当我尝试从我的数据库中获取字符串时,我在获取字符串时遇到“内存不足”异常。

调用反序列化游戏的方法如下。

private HashMap<String, Game> games = new HashMap<String, Game>();

public void load(LocalDatabaseHelper localDbHelper) throws Exception
{
    synchronized(gameLockObject) {
        GameDetailDAO dao = new GameDetailDAO(localDbHelper);

        //this will fetch me the all the entities from databse
        ArrayList<GameDetailEntity> dbGameDetails = dao.getEntities(null, null);

        for (GameDetailEntity gameDetail : dbGameDetails) {
            String gameLevel = gameDetail.getDetailLevel();             

            String gameXml = gameDetail.getGameData();

            Game game = null;
            if(gameLevel.equalsIgnoreCase("Novice")) {
                game = Job.deserialiseJob(gameXml, NoviceLevel.class);
            }
            else if (gameLevel.equalsIgnoreCase("Expert")) { 
                game = Job.deserialiseJob(gameXml, ExpertLevel.class);
            }

            //set the job version
            game.setGameversion(gameDetail.getGameVersion());
            game.setMagicNumber(gameDetail.getMagicNumber());
            game.setInactiveUser(gameDetail.getInactiveUser());
            game.setStartTime(gameDetail.getStartTime());
            game.setFinishTime(gameDetail.getFinishTime());
            game.setGameCompletionTime(gameDetail.getGameCompletionTime());
            if (!StringUtils.isNullOrEmpty(gameDetail.getGameStatus())) {
                game.setGameStatus(GameStatus.valueOf(gameDetail.getGameStatus()));
            }

            //add the job to the store
            games.put(gameDetail.getGameRef().toLowerCase(Locale.getDefault()), game);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的数据库事务如下:

@Override
    protected GameEntity getEntityFromCursor(Cursor cursor) 
    {
        String gameRef = cursor.getString(cursor.getColumnIndex(GAME_REF));
        String detailLevel = cursor.getString(cursor.getColumnIndex(DETAIL_LEVEL));
        int gameVersion = cursor.getInt(cursor.getColumnIndex(GAME_VERSION));
        String gameData = cursor.getString(cursor.getColumnIndex(GAME_DATA));
        String status = cursor.getString(cursor.getColumnIndex(GAME_STATUS));

        long longStart = cursor.getLong(cursor.getColumnIndex(VISIT_START_TIME));
        Date startTime = longStart == -1 ? null : new Date(longStart);

        long longFinish = cursor.getLong(cursor.getColumnIndex(VISIT_END_TIME));
        Date finishTime = longFinish == -1 ? null : new Date(longFinish);

        long longComplete = cursor.getLong(cursor.getColumnIndex(GAME_COMPLETION_TIME));
        Date completionTime = longComplete == -1 ? null : new Date(longComplete);

        GameEntity entity = new GameEntity(gameRef, detailLevel, gameVersion, gameData, );
        entity.setGameStatus(status);
        entity.setStartTime(startTime);
        entity.setFinishTime(finishTime);
        entity.setGameCompletionTime(completionTime);
        return entity;
    }
Run Code Online (Sandbox Code Playgroud)

但是当我尝试从数据库 @Line 获取数据 String gameData = cursor.getString(cursor.getColumnIndex(GAME_DATA));时,出现内存不足错误。根据我的发现,当我在应用程序标签的清单中添加标志 largeHeap=true 时,我的应用程序变得非常慢。还有 developer.android 状态

永远不要仅仅因为内存不足而需要快速修复而请求大堆——只有当您确切地知道所有内存被分配在哪里以及为什么必须保留它时,才应该使用它。然而,即使您确信您的应用程序可以证明大堆是合理的,您也应该尽可能避免请求它。

任何人都可以建议我如何避免这种情况。大多数SO问题都没有使用位图。任何帮助将不胜感激。

And*_*oid 1

我遇到了问题,原因很简单,字符串的大小很大。巨大的。所以我决定减小字符串的大小。我已将图像数据与 XML 分离并存储在不同的表中。这减少了反序列化所需的数据量。我单独重新加载额外的数据。感谢您的回答和您宝贵的时间。