Acessando SharedPreferences através de métodos estáticos
-
25-09-2019 - |
Pergunta
Tenho algumas informações armazenadas como SharedPreferences.Preciso acessar essas informações fora de uma atividade (de uma classe de modelo de domínio).Então criei um método estático em uma Activity que uso apenas para obter as preferências compartilhadas.
Isso está me dando alguns problemas, pois aparentemente não é possível chamar o método "getSharedPreferences" a partir de um método estático.
Aqui está a mensagem que o eclipse está me dando:
Cannot make a static reference to the non-static method
getSharedPreferences(String, int) from the type ContextWrapper
Tentei contornar isso usando uma instância de Activity, assim:
public static SharedPreferences getSharedPreferences () {
Activity act = new Activity();
return act.getSharedPreferences("FILE", 0);
}
Este código fornece uma exceção de ponto nulo.
Existe uma solução alternativa?Estou sentindo o cheiro do código do Android ao tentar fazer isso?
Desde já, obrigado.
Solução
Isso porque neste caso, act
é um objeto que você apenas cria. Você tem que deixar o Android fazer isso por você; getSharedPreferences()
é um método de Context
, (Activity
, Service
e outras classes se estende de Context
). Então, você tem que fazer sua escolha:
Se o método estiver dentro de uma atividade ou outro tipo de contexto:
getApplicationContext().getSharedPreferences("foo", 0);
Se o método estiver fora de uma atividade ou outro tipo de contexto:
// 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());
Outras dicas
A resposta de Cristian é boa, mas se você quiser acessar suas preferências compartilhadas de todos os lugares da maneira certa: seria:
- Criar uma subclasse de
Application
, por exemplopublic class MyApp extends Application {
... - Colocou o
android:name
atributo do seu<application>
Tag no Androidmanifest.xml para apontar para sua nova classe, por exemploandroid:name="MyApp"
(então a classe é reconhecida pelo Android) - No método onCreate () da sua instância do aplicativo, salve seu contexto (por exemplo,
this
) para um campo estático nomeadoapp
e crie um método estático que retorne este campo, por exemplogetApp()
. Você pode usar esse método posteriormente para obter um contexto do seu aplicativo e, portanto, obter suas preferências compartilhadas. :-)
Eu tive um problema semelhante e resolvi simplesmente passando o contexto atual para a função estática:
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);
}
Como você está ligando de fora de uma atividade, será necessário salvar o contexto:
public static Context context;
E dentro do OnCreate:
context = this;
Armazenar o contexto como uma variável estática pode causar problemas porque quando a classe é destruída, o mesmo ocorre com as variáveis estáticas.Isso às vezes acontece quando o aplicativo é interrompido e fica com pouca memória.Apenas certifique-se de que o contexto esteja sempre definido antes de tentar usá-lo, mesmo quando a classe que define o contexto for destruída aleatoriamente.
Esta é uma alternativa melhor para armazenar suas preferências compartilhadas em campos estáticos.
- Semelhante ao que foi sugerido aqui, crie uma classe que estenda Application
- Faça com que o construtor da sua classe use Context como parâmetro.
- Use seu contexto para obter preferências compartilhadas e armazená-las em variáveis privadas.
- Crie variáveis públicas para retornar os dados recuperados.
por exemplo
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;
}
}
uso em sua atividade
UserInfo user = new UserInfo(this.getApplicationContext());
String SAVED_USERNAME = user.getSavedUserName();
String SAVED_USERID = user.getSavedUserID();
Eu tinha a mesma necessidade – algumas das minhas preferências precisam ser acessadas com frequência e de forma eficiente.Também imagino que ler e escrever uma string em SharedPreferences seja um pouco mais lento do que obter e definir uma variável estática (mas provavelmente em um grau insignificante).Eu também me acostumei a usar campos estáticos, recuperando valores de preferência apenas na inicialização e salvando-os ao fechar.
Não adorei minhas opções para manter referências estáticas diretamente aos SharedPreferences/contextos, mas até agora essa solução alternativa foi suficiente.
Minha solução:
Crie uma classe Configurações com todas as variáveis estáticas necessárias.
Quando o aplicativo for inicializado, recupere os campos SharedPreferences e defina imediatamente todos os campos Configurações (eu chamo um método "loadSharedPrefs()" no final do método onCreate de MainActivity).
Na inicialização do preferChangeListener de SettingsActivity, defina o campo estático apropriado na classe Configurações.(Eu chamo um método "setAppropriateSetting (key, value)" no início do onPreferenceChange () de SettingsActivity).
Use suas preferências estáticas onde e quando quiser!
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);
}