Доступ к SharedPreferences через статические методы

У меня есть некоторая информация, хранящаяся как SharedPreferences. Мне нужно получить доступ к этой информации из внешнего вида деятельности (из класса модели домена). Поэтому я создал статический метод в Activity, который я использую только для получения общих настроек.

Это вызывает у меня некоторые проблемы, поскольку, по-видимому, невозможно вызвать метод getSharedPreferences из статического метода.

Вот сообщение, которое затмение дает мне:

Cannot make a static reference to the non-static method 
getSharedPreferences(String, int) from the type ContextWrapper

Я попытался обойти это с помощью экземпляра Activity, например так:

public static SharedPreferences getSharedPreferences () {
  Activity act = new Activity();
  return act.getSharedPreferences("FILE", 0);
}

Этот код дает исключение нулевой точки.

Есть ли обходной путь? Я вхожу в запах кода Android, пытаясь сделать это?

Заранее спасибо.

Ответы на вопрос(6)

У меня была похожая проблема, и я решил ее, просто передав текущий контекст статической функции:

public static void LoadData(Context context)
{
    SharedPreferences SaveData = context.getSharedPreferences(FILENAME, MODE_PRIVATE);
    Variable = SaveData.getInt("Variable", 0);
    Variable1 = SaveData.getInt("Variable1", 0);
    Variable2 = SaveData.getInt("Variable2", 0);
}

Поскольку вы звоните извне действия, вам нужно сохранить контекст:

public static Context context;

И внутри OnCreate:

context = this;

Хранение контекста как статической переменной может вызвать проблемы, потому что когда класс уничтожается, статические переменные тоже. Это иногда случается, когда приложение прерывается и становится недостаточно памяти. Просто убедитесь, что контекст всегда установлен, прежде чем пытаться использовать его, даже если класс, устанавливающий контекст, случайно уничтожен.

public static String getPreferenceValue(Context context) {
    SharedPreferences sharedPreferences = 
        PreferenceManager.getDefaultSharedPreferences(context);
    String key = context.getString(R.string.pref_key);
    String defaultVal = context.getString(R.string.pref_default);
    return sharedPreferences.getString(key,defaulVal);
}

У меня была такая же потребность - к некоторым из моих предпочтений нужно обращаться часто и эффективно. Я также представляю, что чтение и запись строки из SharedPreferences немного медленнее, чем получение и установка статической переменной (но, вероятно, в незначительной степени). Я также просто привык к использованию статических полей, получая значения предпочтений только при запуске и сохраняя их при закрытии.

Мне не нравились мои варианты хранения статических ссылок на SharedPreferences / context напрямую, но пока этого обходного пути было достаточно.

Мое решение:

Создайте класс Settings со всеми необходимыми статическими переменными.

Когда приложение инициализируется, извлекайте поля SharedPreferences и сразу устанавливайте все поля настроек (я вызываю метод loadSharedPrefs () в конце метода onCreate MainActivity).

В инициализации preferenceChangeListener SettingsActivity установите соответствующее статическое поле в классе Settings. (Я вызываю метод "setAppresponSetting (key, value)" в начале onPreferenceChange ()) SettingsActivity.

Используйте ваши статические предпочтения где угодно и когда угодно!

Ответ Кристиана хорош, но если вы хотите получить доступ к своим общим настройкам из любого места, правильный путь будет следующим:

Создать подклассApplicationнапример,public class MyApp extends Application {...Установитьandroid:name атрибут вашего<application> тег в AndroidManifest.xml, чтобы указать на ваш новый класс, например,android:name="MyApp" (таким образом, класс распознается Android)В методе onCreate () вашего экземпляра приложения сохраните свой контекст (например,this) к статическому полю с именемapp и создать статический метод, который возвращает это поле, например,getApp(), Затем вы можете использовать этот метод позже, чтобы получить контекст вашего приложения и, следовательно, получить ваши общие настройки. :-)
 MyNameIsZero07 окт. 2010 г., 21:07
+1 за информационный комментарий.
 lm2a19 мая 2016 г., 12:54
Это отличная идея добавить SharedPreferences в шаблон репозитория в контексте MVP без необходимости передавать контекст в качестве параметра.
 Cristian28 сент. 2010 г., 06:57
+1 Вау ... люблю эту идею.
 efr4k20 янв. 2013 г., 13:37
Действительно хороший ответ. Будет ли это также работать для создания метода getApp () в «основной» деятельности, которая, в свою очередь, вызывает getApplicationContext ()? Или это может в некоторых редких случаях привести к нулевому исключению?
 Matthew Quiros26 нояб. 2012 г., 13:47
^ Это может привести к ошибкам, если у вас есть тревоги, которые повторяются в фоновом режиме, пока устройство включено и приложениене запускается вручную. С другой стороны, если ваш вариант использования всегда включает ручной запуск приложения, это, вероятно, не имеет значения.
 user45857725 апр. 2013 г., 18:57
Вы не должны сохранять контексты в статических переменных, так как это может исчерпать память вашего приложения.
 StingRay512 дек. 2012 г., 11:36
Это действительно помогло мне в поисках некоторых ошибок в моем приложении! Спасибо!
 Matthew Quiros24 нояб. 2012 г., 14:09
Это не очень хороший подход. Когда Android завершает процесс или когда телефон перезагружается, статическая переменнаяapp будет иметь нулевое значение, потому чтоonCreated не будет вызван сразу.
 mreichelt26 нояб. 2012 г., 13:21
@MattQuiros: Если бы это было так, то многие из моих приложений выдавали бы исключения в этой строке. Они не Точнее, Application # onCreate () вызываетсявсегда когда приложение запущено.
 mreichelt22 янв. 2013 г., 17:15
@ephrack Не очень хорошая идея. Деятельность не всегда может быть доступна. Android разрешено завершать процесс и перезапускать любое действие, не зная, что определенное действие было начато.
Решение Вопроса

Это потому, что в этом случаеact это объект, который вы только что создали. Вы должны позволить Android сделать это за вас;getSharedPreferences() это методContext, (Activity, Service и другие классы простираются отContext). Итак, вы должны сделать свой выбор:

Если метод находится внутри действия или другого вида контекста:

getApplicationContext().getSharedPreferences("foo", 0);

Если метод находится вне действия или другого вида контекста:

// you have to pass the context to it. In your case:
// this is inside a public class
public static SharedPreferences getSharedPreferences (Context ctxt) {
   return ctxt.getSharedPreferences("FILE", 0);
}

// and, this is in your activity
YourClass.this.getSharedPreferences(YourClass.this.getApplicationContext());
 MyNameIsZero07 окт. 2010 г., 21:07
Благодарю. Мое решение основано на вашем предложении.
 Code Spy03 мая 2018 г., 12:48
Без контекста мы можем сделать этоfreakyjolly.com/shared-preference-context-error-android
 goonerDroid28 июл. 2014 г., 09:10
Хорошо !! работал на мой запрос

Вот лучшая альтернатива хранению ваших общих настроек в статических полях.

Подобно тому, что было предложено здесь, создайте класс, расширяющий ApplicationЗаставьте конструктор для вашего класса принять Context как параметр.Используйте свой контекст, чтобы получить общие настройки и сохранить их в частных переменных.Создайте открытые переменные для возврата полученных данных.

например

public class UserInfo extends Application{
    private String SAVED_USERID;
    private String SAVED_USERNAME;

    public UserInfo(Context context) {
        SharedPreferences prefs = context.getSharedPreferences(FILE, MODE_PRIVATE);
        SAVED_USERNAME = prefs.getString("UserName", null);
        SAVED_USERID = prefs.getString("UserID", null);
    }

    public String getSavedUserName() {
        return SAVED_USERNAME;
    }

    public String getSavedUserID() {
         return SAVED_USERID;
    }
}

использование в вашей деятельности

   UserInfo user = new UserInfo(this.getApplicationContext());

   String SAVED_USERNAME = user.getSavedUserName();
   String SAVED_USERID = user.getSavedUserID();
 Hein Andre Grønnestad22 мар. 2016 г., 13:51
Почему это должно быть продленоApplication?

Ваш ответ на вопрос