Android: статическая переменная ноль при нехватке памяти - PullRequest
24 голосов
/ 25 января 2011

У меня есть приложение, в котором есть статические переменные.Эти переменные хранятся в независимом классе с именем DataContext.Эти переменные инициализируются из необработанных файлов при запуске приложения (метод с именем DataContext.initConstant () вызывается в onCreate () MyApplication, который расширяет Application).

(EDIT: метод initConstant использует AsyncTask длязагрузить эти данные из файлов).

Когда мое приложение выходит на задний план в течение определенного времени или когда мое приложение использует много памяти, эти статические переменные становятся равными нулю.

  1. Как это можно предотвратить?

  2. Если нет, что мне делать с моими статическими переменными?

    У меня есть другие данные, которые хранятся в статических переменных, которые будут использоваться во всехразличные действия, но я очищаю их или передаю их в null в onLowMemory() MyApplication.

  3. Каков наилучший способ сделать некоторые данные доступными между действиями, если эти данные слишком великиЧтобы быть сериализованным в Intent, база данных не может использоваться (по какой-либо причине) и не может быть сохранена в файлах через сериализацию?

Ответы [ 7 ]

5 голосов
/ 25 января 2011

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

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

4 голосов
/ 25 января 2011
  1. Вы не можете.Android должен время от времени освобождать память.Представьте себе, если бы во всех приложениях была тонна статических данных, которые должны постоянно храниться - как бы вы поместили это в память?Это мобильный телефон.У него нет виртуальной памяти.

  2. (и 3): все, что должно быть постоянным, должно храниться либо с помощью SharedPreferences, базы данных Sqlite или файла.

2 голосов
/ 27 марта 2013

Я предполагаю, что это проблема с кешем данных.

Хранение данных в статическом классе не гарантируется, когда пользователи часто меняют приложения.Система Android будет восстанавливать любую фоновую активность, когда памяти мало.Статический класс определенно относится к этой категории.

Правильный способ сделать это - использовать sharedPreference для сохранения данных кэша.

Вы можете создать свой собственный метод получения и установкиданные, которые вы хотите, и оберните их вокруг объекта sharedPreference.Когда вы получаете доступ с помощью getter, вы всегда должны проверять, является ли значение пустым или срок его действия истек.Вы можете сохранить update_time при использовании setter.

Для данных, относящихся к конкретной деятельности, вы можете просто использовать getPreference(permission), если вы хотите обмениваться данными между действиями и другими компонентами приложений, вы можете использовать getSharedPreference(name, permission).

Обычно разрешение будет MODE_PRIVATE, так что доступ к данным возможен только в вашем приложении.

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

editor.clear(); editor.commit()

Если вы хотите кэшировать сложный объект, вы должны сериализоватьЭто.Я предпочитаю формат JSON.Так что вам нужен какой-то механизм преобразования на месте.Для этого я создам свой класс объектов данных, расширяющий класс JSONable.Класс JSONable будет иметь метод toJSON() и readFromJSON().Это удобно при восстановлении и сериализации данных.

2 голосов
/ 25 января 2011

Если вы не используете необработанные файлы, я бы посоветовал инициализировать, когда класс загружен.

Например,

public static Map<?,?> myStaticMap = new HashMap<?,?>();
static { //fill myStaticMap }

Если вы загружаете файлы таким образом, у вас есть более серьезные проблемы. Например, как насчет ошибок ввода-вывода или задержки? Вы получите предупреждения в gingerbread (если вы их включите) для выполнения ввода / вывода в вашем основном потоке. Возможно, у вас должен быть объект для извлечения этих значений вместо класса со статическими полями. (возможно со статическим кешем, хотя вы должны синхронизироваться с ним перед проверкой / изменением)

1 голос
/ 28 августа 2012

В вашем методе onResume() вы можете запросить статические данные, чтобы увидеть, есть ли они, и если нет, загрузить их снова.

1 голос
/ 25 января 2011

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

Intent i = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                context.startActivity(i);

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

0 голосов
/ 19 января 2012

Вместо использования статической переменной вы можете использовать общую настройку для хранения значения.

Примечание: для общих предпочтений также не следует давать большую нагрузку.

Я решил эту проблему с помощью суперкласса с функциями получения и установки для хранения и извлечения переменной общего предпочтения.

Все классы в моем приложении расширили суперкласс вместо активности.

...