Подтвердить что ты не робот

Android: статическая переменная null на низкой памяти

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

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

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

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

  • Если не то, что я должен делать с моими статическими переменными?

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

Например,

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

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

Ответ 4

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

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

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

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

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

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

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

editor.clear(); editor.commit()

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

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

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

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

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