OutOfMemoryError при попытке сохранить большие данные в SharedPreferences, Android

Проблема: я хочу сохранить огромную карту объектов (1000 контактов) в SharedPreferences.

У меня есть приложение Cordova, где в первый раз загружаются все контакты и конвертируются все фотографии в строку base64.

Обычно этот процесс может занять около 30 секунд. По этой причине моя цель сохранить все контакты в виде строки в SharedPreferences для быстрой загрузки.

Я использую библиотеку GSON, но что бы я ни делал, я получаю:

java.lang.OutOfMemoryError
       at java.lang.String.<init>(String.java:354)
       at java.lang.String.<init>(String.java:171)
       at java.io.ByteArrayOutputStream.toString(ByteArrayOutputStream.java:137)

Это мой метод, когда я конвертирую свою карту в ByteArrayOutputStream, но получаю исключение в последней строке: out.toString()


public static String getStrFromGroupsListJSONObject(ConcurrentHashMap<String, WmContactImage> contactMap){

        Gson gson = getInstance();  
        OutputStream out = new ByteArrayOutputStream();

        try {
            JsonWriter writer = new JsonWriter(new OutputStreamWriter(out, "UTF-8"));

            Iterator<String> it = contactMap.keySet().iterator();

            WmContactImage img;

            writer.beginObject(); // {


            while(it.hasNext()){
                String key = it.next();

                writer.name(key);

                img = contactMap.get(key);

                gson.toJson(img, WmContactImage.class, writer);
            }           

            writer.endObject();   // }
            writer.close();             
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return out.toString();
    } 

Есть ли другой способ сохранить карту в SharedPreferences или я могу как-то сохранить OutputStream?


person snaggs    schedule 21.09.2014    source источник
comment
Я хочу хранить огромную карту объектов (1000 контактов) в SharePreferences — зачем? Если это в формате JSON, используйте файл JSON.   -  person CommonsWare    schedule 22.09.2014
comment
@CommonsWare У меня нет JSON. Я пытаюсь создать один. Если я преобразую свою MAP в строку JSON, я получу OutOfMemoryError. Поэтому я использовал JsonWriter. но все же получите то же исключение при попытке получить строку из ByteArrayOutputStream. Спасибо,   -  person snaggs    schedule 22.09.2014
comment
@CommonsWare единственный способ, который может сработать, - это разделить карту на несколько частей и сохранить одну за другой.   -  person snaggs    schedule 22.09.2014


Ответы (2)


Используйте файл http://developer.android.com/guide/topics/data/data-storage.html . общие настройки не должны хранить большие данные. Используйте файл или базу данных sqlote.

person eduyayo    schedule 21.09.2014

Общие настройки — не лучший вариант, если вы хотите хранить огромные объемы данных. Вероятно, вам следует использовать базу данных SQLite на устройстве. Вы можете прочитать в документацию, как именно это сделать.

person TmKVU    schedule 21.09.2014
comment
Я знаю, но на самом деле мне нужно только SELECT *. Насколько я знаю, SQLite медленнее, чем SharePreferences, и его полезно использовать, когда вы хотите выполнить некоторые запросы с условиями. - person snaggs; 22.09.2014
comment
@fessy As I know SQLite is slower then SharePreferences - откуда ты знаешь? Вы измерили это? ТмКВУ прав. SharedPreferences — это не выход. Если вам не нужен SQLite (который для 1000 контактов будет очень быстрым), сохраните файл JSON. - person Simon; 22.09.2014
comment
@Simon Хотя поиск определенных ключей может быть медленным, это не повлияет на вашу производительность. Поскольку вы будете запрашивать весь набор данных, поиск не требуется, и вы практически запрашиваете весь файл удобным способом. - person TmKVU; 22.09.2014