SQL Cursor выкидывает из памяти при вызове getString

Приложение Ссылка на мой предыдущий вопрос: – Недостаточно памяти

Я постараюсь быть максимально точным. Я получаю ответ от моего веб-сервиса, который вызывает длинную строку base64. Я декодирую строку и получаю огромную строку, которая содержит мои данные. Я де-сериализую строку и создаю объект своего класса, используя строку, как показано ниже.

String decryptedXml = XmlObject.toDecryptedXmlString(gameDetail.getGameData(), app.getSessionEncryptionKey()); Game noviceGame = deserialiseGame(decryptedXml, NoviceGamer.class); 

DesrialiseGame () – это просто метод, который десриализует данные и создает и возвращает мой игровой экземпляр. Чтобы сохранить этот объект на нескольких сеансах (вход / выход), я сохраняю всю свою игру (мою строку, чья де-сериализация дала мне экземпляр Game) в базе данных.

В следующий раз при входе пользователя в систему, чтобы создать экземпляр игры, я получаю строку из моей БД и снова пытаюсь де-сериализовать, чтобы вернуть экземпляр игры. Но когда я пытаюсь получить строку из моего БД, я получаю исключение «OUT OF MEMORY» при извлечении строки.

Метод, который называется Де-сериализация игры, приведен ниже.

 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); } } } 

Моя транзакция базы данных выглядит следующим образом:

 @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; } промежуток @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; } 

Но когда я пытаюсь извлечь данные из базы данных @Line String gameData = cursor.getString(cursor.getColumnIndex(GAME_DATA)); Я выхожу из памяти. Согласно моему выводу, когда я добавляю флаг largeHeap = true в манифест в теге приложения, мое приложение чертовски медленно. А также состояния разработчика.

Никогда не запрашивайте большую кучу просто потому, что у вас закончилась нехватка памяти, и вам нужно быстрое исправление – вы должны использовать ее только тогда, когда вы точно знаете, где находится вся ваша память, и почему ее необходимо сохранить. Тем не менее, даже если вы уверены, что ваше приложение может оправдать большую кучу, вы должны избегать его запроса в любой возможной степени.

Может ли кто-нибудь предложить мне, как этого избежать. Нет никакого растрового использования, которое содержит большинство вопросов SO. Любая помощь будет оценена по достоинству.

SQLCipher для Android выделяет буфер памяти для каждого окна курсора с максимальным размером 1 МБ. Поскольку вы прокомментировали, что файл данных игры достаточно велик, размер, вероятно, превышает максимальный размер окна курсора, вызывая ошибку выделения памяти. В этом случае мы, вероятно, рекомендуем один из двух вариантов:

  1. Нормализовать игровые данные в более типичные структуры базы данных (т. Е. Несколько таблиц, столбцов, строк).
  2. Разделите файл данных игры на фрагменты, каждый из которых меньше 1 МБ, а затем соберите их в приложении.

Я столкнулся с проблемой из-за простой причины, размер строки был огромным. ОГРОМНЫЙ. Поэтому я решил уменьшить размер строки. Я отделил данные изображения от XML и сохранил их в другой таблице. Это уменьшает объем данных, необходимых для де-сериализации. Я загружаю дополнительные данные отдельно. Спасибо за ответы и за ваше драгоценное время.

Intereting Posts
Как сгенерировать apk на сервере с изменением имени приложения и значка автоматически в Android? Оверлей экрана обнаружены блоки Android-разрешения Преобразование Json Array в обычный Java-массив Android Studio – невозможно разрешить символ «firebase» Как решить проект загрузки студии Android? Не удается загрузить проект: java.lang.IllegalStateException: метод @NotNull Настройте EditText на размер шрифта Как реализовать дизайн материалов «Текстовое поле полной ширины»? Как использовать DataItem для Android Wear Клиент Google API не подключается снова после того, как onConnectionSuspended (int Cause) вызван Как получить формат длинной долготы E6 для Google Maps на Android Android 3.x / HLS, как начать в конце потока Firebase Android: событие onDataChange () всегда выполняется в главном потоке пользовательского интерфейса? Изменить фон LinearLayout на Android Отклонить диалоговое окно после изменения ориентации экрана Поле не вводится в проект Android Dagger