我正在尝试编写一个单例类来监督涉及共享首选项的所有操作。
我有3个首选项文件,常规,设置和临时
我希望能够使用此类编写给定类型的首选项,例如:
stg_full_screen: true // as boolean
这是我到目前为止所做的:
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
public class SharedPrefManager extends Activity {
// Globals
private int GENERAL = 1000;
private int SETTINGS = 2000;
private int TEMP_STORE = 3000;
private String PREF_GENERAL = "com.example.general";
private String PREF_SETTINGS = "com.example.settings";
private String PREF_TEMP_STORE = "com.example.temp_store";
private SharedPreferences general;
private SharedPreferences settings;
private SharedPreferences tempStore;
private SharedPreferences.Editor general_editor;
private SharedPreferences.Editor settings_editor;
private SharedPreferences.Editor temp_store_editor;
// Instantiate singleton object
private static SharedPrefManager ourInstance = new SharedPrefManager();
public static SharedPrefManager getInstance() { return ourInstance; }
private SharedPrefManager() {
// Get handle on all preference files
general = getSharedPreferences(PREF_GENERAL, Context.MODE_PRIVATE);
settings = getSharedPreferences(PREF_SETTINGS, Context.MODE_PRIVATE);
tempStore = getSharedPreferences(PREF_TEMP_STORE, Context.MODE_PRIVATE);
// provision editors for all preference files
general_editor = general.edit();
settings_editor = settings.edit();
temp_store_editor = tempStore.edit();
}
private String read_prefs (String pref_name) {
// this method reads a preference and returns it
// ideally, i would want to be able to return appropriate types by request
// e.g boolean, string
return null;
}
private void write_prefs (String pref_name, String pref_val) {
// this method would take a preference and write the appropriate type to prefs
}
// this method determines where to put a preference by checking the name of the key
// this works because i use the following naming conventions
// stg_name for settings, tmp_name for all that goes into tempStore
private String resolve_pref_category (String path) {
if (path.startsWith("stn")) return PREF_SETTINGS;
else if (path.startsWith("tmp")) return PREF_TEMP_STORE;
else return PREF_GENERAL;
}
}
我的问题是:
由于
答案 0 :(得分:25)
正确的单身共享首选项类。它可能对将来的其他人有所帮助。
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
public class SharedPref
{
private static SharedPreferences mSharedPref;
public static final String NAME = "NAME";
public static final String AGE = "AGE";
public static final String IS_SELECT = "IS_SELECT";
private SharedPref()
{
}
public static void init(Context context)
{
if(mSharedPref == null)
mSharedPref = context.getSharedPreferences(context.getPackageName(), Activity.MODE_PRIVATE);
}
public static String read(String key, String defValue) {
return mSharedPref.getString(key, defValue);
}
public static void write(String key, String value) {
SharedPreferences.Editor prefsEditor = mSharedPref.edit();
prefsEditor.putString(key, value);
prefsEditor.commit();
}
public static boolean read(String key, boolean defValue) {
return mSharedPref.getBoolean(key, defValue);
}
public static void write(String key, boolean value) {
SharedPreferences.Editor prefsEditor = mSharedPref.edit();
prefsEditor.putBoolean(key, value);
prefsEditor.commit();
}
public static Integer read(String key, int defValue) {
return mSharedPref.getInt(key, defValue);
}
public static void write(String key, Integer value) {
SharedPreferences.Editor prefsEditor = mSharedPref.edit();
prefsEditor.putInt(key, value).commit();
}
}
只需在MainActivity上调用SharedPref.init()
SharedPref.init(getApplicationContext());
*写数据*
SharedPref.write(SharedPref.NAME, "XXXX");//save string in shared preference.
SharedPref.write(SharedPref.AGE, "25");//save int in shared preference.
SharedPref.write(SharedPref.IS_SELECT, true);//save boolean in shared preference.
读取数据
String name = SharedPref.read(SharedPref.NAME, null);//read string in shared preference.
String age = SharedPref.read(SharedPref.AGE, 0);//read int in shared preference.
String isSelect = SharedPref.read(SharedPref.IS_SELECT, false);//read boolean in shared preference.
*输出:*
Name : "XXXX";
Age : "25";
IsSelect : "true";
答案 1 :(得分:21)
通常,我使用这样的东西:
没有静态Context
引用,每个属性的静态getter / setter,在需要时,您可以为某些属性添加内存缓存值,以便从内存中更快地获取它,而不是从SharedPreferences中读取。明确的api。
public class SharedPreferencesManager {
private static final String APP_SETTINGS = "APP_SETTINGS";
// properties
private static final String SOME_STRING_VALUE = "SOME_STRING_VALUE";
// other properties...
private SharedPreferencesManager() {}
private static SharedPreferences getSharedPreferences(Context context) {
return context.getSharedPreferences(APP_SETTINGS, Context.MODE_PRIVATE);
}
public static String getSomeStringValue(Context context) {
return getSharedPreferences(context).getString(SOME_STRING_VALUE , null);
}
public static void setSomeStringValue(Context context, String newValue) {
final SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putString(SOME_STRING_VALUE , newValue);
editor.commit();
}
// other getters/setters
}
答案 2 :(得分:2)
Kotlin 示例,用于使用anrdoidx的安全性加密库(最低API 23)进行双重用途的加密和未加密共享首选项。
我在需要的地方使用Dagger2将其作为@Singleton注入。
在Dagger模块中使用@Name批注来区分SharedPreferences实例,并且可以有2个独立的.xml文件(1个加密,1个未加密)来读写。
如果您不想要加密的东西,请撕掉;-D。
添加到build.gradle中的依赖项:
implementation "androidx.security:security-crypto:1.0.0-beta01"
import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
class Prefs(prefsName: String, context: Context) {
private lateinit var ANDX_SECURITY_KEY_KEYSET: String
private lateinit var ANDX_SECURITY_VALUE_KEYSET: String
private lateinit var cntext: Context
private lateinit var prefName: String
private lateinit var prefs: SharedPreferences
constructor(
prefsName: String,
context: Context,
masterKeyAlias: String,
prefKeyEncryptionScheme: EncryptedSharedPreferences.PrefKeyEncryptionScheme,
prefValueEncryptionScheme: EncryptedSharedPreferences.PrefValueEncryptionScheme
): this(prefsName, context) {
ANDX_SECURITY_KEY_KEYSET = "__androidx_security_crypto_encrypted_prefs_key_keyset__"
ANDX_SECURITY_VALUE_KEYSET = "__androidx_security_crypto_encrypted_prefs_value_keyset__"
cntext = context
prefName = prefsName
prefs =
EncryptedSharedPreferences.create(
prefsName,
masterKeyAlias,
context,
prefKeyEncryptionScheme,
prefValueEncryptionScheme
)
}
init {
if (!::ANDX_SECURITY_KEY_KEYSET.isInitialized) {
prefs =
context.getSharedPreferences(
prefsName,
Context.MODE_PRIVATE
)
}
}
companion object {
const val INVALID_BOOLEAN: Boolean = false
const val INVALID_FLOAT: Float = -11111111111F
const val INVALID_INT: Int = -1111111111
const val INVALID_LONG: Long = -11111111111L
const val INVALID_STRING: String = "INVALID_STRING"
val INVALID_STRING_SET: Set<String> = setOf(INVALID_STRING)
}
/**
* OnChangeListener
* */
fun registerOnSharedPreferenceChangeListener(
listener: SharedPreferences.OnSharedPreferenceChangeListener) =
prefs.registerOnSharedPreferenceChangeListener(listener)
fun unregisterOnSharedPreferenceChangeListener(
listener: SharedPreferences.OnSharedPreferenceChangeListener) =
prefs.unregisterOnSharedPreferenceChangeListener(listener)
/**
* Read Shared Prefs
* */
fun contains(key: String): Boolean =
prefs.contains(key)
fun getAll(): Map<String, *> =
prefs.all
// Returns null if the Boolean value is not in
// Shared Preferences
fun read(key: String): Boolean? =
if (contains(key)) {
read(key, INVALID_BOOLEAN)
} else {
null
}
// Boolean
fun read(key: String, returnIfInvalid: Boolean): Boolean =
prefs.getBoolean(key, returnIfInvalid)
// Float
fun read(key: String, returnIfInvalid: Float): Float =
prefs.getFloat(key, returnIfInvalid)
// Int
fun read(key: String, returnIfInvalid: Int): Int =
prefs.getInt(key, returnIfInvalid)
// Long
fun read(key: String, returnIfInvalid: Long): Long =
prefs.getLong(key, returnIfInvalid)
// Set<String>
fun read(key: String, returnIfInvalid: Set<String>): Set<String>? =
prefs.getStringSet(key, returnIfInvalid)
// String
fun read(key: String, returnIfInvalid: String): String? =
prefs.getString(key, returnIfInvalid)
/**
* Modify Shared Prefs
* */
fun clear() {
if (::ANDX_SECURITY_KEY_KEYSET.isInitialized) {
val clearTextPrefs = cntext.getSharedPreferences(prefName, Context.MODE_PRIVATE)
val keyKeyset = clearTextPrefs.getString(ANDX_SECURITY_KEY_KEYSET, INVALID_STRING)
val valueKeyset = clearTextPrefs.getString(ANDX_SECURITY_VALUE_KEYSET, INVALID_STRING)
if (keyKeyset != null && keyKeyset != INVALID_STRING
&& valueKeyset != null && valueKeyset != INVALID_STRING) {
if (!clearTextPrefs.edit().clear().commit()) {
clearTextPrefs.edit().clear().apply()
}
if (!clearTextPrefs.edit().putString(ANDX_SECURITY_KEY_KEYSET, keyKeyset).commit()) {
clearTextPrefs.edit().putString(ANDX_SECURITY_KEY_KEYSET, keyKeyset).apply()
}
if (!clearTextPrefs.edit().putString(ANDX_SECURITY_VALUE_KEYSET, valueKeyset).commit()) {
clearTextPrefs.edit().putString(ANDX_SECURITY_VALUE_KEYSET, valueKeyset).apply()
}
}
} else {
if (!prefs.edit().clear().commit()) {
prefs.edit().clear().apply()
}
}
}
fun remove(key: String) {
if (!prefs.edit().remove(key).commit()) {
prefs.edit().remove(key).apply()
}
}
// Boolean
fun write(key: String, value: Boolean) {
if (!prefs.edit().putBoolean(key, value).commit()) {
prefs.edit().putBoolean(key, value).apply()
}
}
// Float
fun write(key: String, value: Float) {
if (!prefs.edit().putFloat(key, value).commit()) {
prefs.edit().putFloat(key, value).apply()
}
}
// Int
fun write(key: String, value: Int) {
if (!prefs.edit().putInt(key, value).commit()) {
prefs.edit().putInt(key, value).apply()
}
}
// Long
fun write(key: String, value: Long) {
if (!prefs.edit().putLong(key, value).commit()) {
prefs.edit().putLong(key, value).apply()
}
}
// Set<String>
fun write(key: String, value: Set<String>) {
if (!prefs.edit().putStringSet(key, value).commit()) {
prefs.edit().putStringSet(key, value).apply()
}
}
// String
fun write(key: String, value: String) {
if (!prefs.edit().putString(key, value).commit()) {
prefs.edit().putString(key, value).apply()
}
}
}
using Dagger2 to inject as a @Singleton的另一种选择是:
AppPrefs.kt
object AppPrefs {
lateinit var encryptedPrefs: Prefs
lateinit var prefs: Prefs
// Add your key strings here...
fun initEncryptedPrefs(context: Context) {
encryptedPrefs =
Prefs(
"ENCRYPTED_PREFS",
context,
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}
fun initPrefs(context: Context) {
prefs = Prefs("PREFS", context)
}
}
Application.kt
class Application: Application() {
override fun onCreate() {
super.onCreate()
AppPrefs.initEncryptedPrefs(this.applicationContext)
AppPrefs.initPrefs(this.applicationContext)
}
}
然后仅从AppPrefs.prefs
或AppPrefs.encryptedPrefs
的任何地方拨打电话
答案 3 :(得分:1)
科特林解决方案:
object PrefsHelper {
private lateinit var prefs: SharedPreferences
private const val PREFS_NAME = "params"
const val ID_USER = "id_user"
const val TOKEN = "token"
fun init(context: Context) {
prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
}
fun read(key: String, value: String): String? {
return prefs.getString(key, value)
}
fun read(key: String, value: Long): Long? {
return prefs.getLong(key, value)
}
fun write(key: String, value: String) {
val prefsEditor: SharedPreferences.Editor = prefs.edit()
with(prefsEditor) {
putString(key, value)
commit()
}
}
fun write(key: String, value: Long) {
val prefsEditor: SharedPreferences.Editor = prefs.edit()
with(prefsEditor) {
putLong(key, value)
commit()
}
}
}
在第一个应用运行时调用init()
函数。
答案 4 :(得分:1)
SharedPreferences具有ApplicationContext的单例
public class SharedPrefsSingleton {
private SharedPreferences sharedPref;
private Context appContext;
private static SharedPrefsSingleton instance;
public static synchronized SharedPrefsSingleton getInstance(Context applicationContext){
if(instance == null)
instance = new SharedPrefsSingleton(applicationContext);
return instance;
}
private SharedPrefsSingleton(Context applicationContext) {
appContext = applicationContext;
sharedPref = appContext.getSharedPreferences(
appContext.getString(R.string.key_pref), Context.MODE_PRIVATE );
}
public void writeData(float value) {
SharedPreferences.Editor editor = sharedPref.edit();
editor.putFloat(appContext.getString(R.string.key_data), value);
editor.apply();
}
public float readData() {
return sharedPref.getFloat(appContext.getString(R.string.key_data), 0);
}
}
答案 5 :(得分:1)
import android.content.Context; 导入android.content.SharedPreferences;
导入com.example.day.weeklypapers.model.LoginModel; 导入com.google.gson.Gson;
公共类WeeklyPreference {
private static WeeklyPreference mInstance = null;
private static SharedPreferences mPreferences;
private static SharedPreferences.Editor mEditor;
private Context context;
private static String SharedPreferenceKey = "Weekly" ;
private WeeklyPreference() {
}
public static WeeklyPreference getInstance(Context context) {
if (mInstance == null) {
mInstance = new WeeklyPreference();
}
if (mPreferences == null) {
mPreferences = context.getApplicationContext().getSharedPreferences(SharedPreferenceKey, Context.MODE_PRIVATE);
mEditor = mPreferences.edit();
mEditor.commit();
}
return mInstance;
}
public void saveInPreference(String key, String value) {
mEditor.putString(key, value);
mEditor.commit();
}
public String getFromPreference(String key) {
return mPreferences.getString(key, "");
}
public LoginModel getUserDetails() {
String userJson = mPreferences.getString(PrefrenceConstants.KEY_USER_JSON_DETAILS, "");
LoginModel user = null;
if (userJson != null && !userJson.equals("")) {
user = new Gson().fromJson(userJson, LoginModel.class);
}
return user;
}
public void saveUserDetails(LoginModel user) {
mEditor.putString(PrefrenceConstants.KEY_USER_JSON_DETAILS, new Gson().toJson(user));
mEditor.commit();
}
public boolean isAutoLogin() {
String userJson = mPreferences.getString(PrefrenceConstants.KEY_USER_JSON_DETAILS, "");
LoginModel user = null;
if (userJson != null && !userJson.equals("")) {
user = new Gson().fromJson(userJson, LoginModel.class);
return user != null;
} else {
return false;
}
}
}
您可以在此单例课程中直接传递pojo类或Model类 减轻精力
保重.. 享受。
答案 6 :(得分:0)
我提出了我的版本,该版本从Max Zonov的答案开始。 我创建了一个抽象类,实现了与特定项目无关的读写操作,因此适合在“核心”模块中进行定义。
import android.content.SharedPreferences
abstract class SharedPreferenceWrapper {
protected lateinit var prefs: SharedPreferences
fun isInitialized() = ::prefs.isInitialized
open fun read(key: String, defValue: Any): Any? {
return when(defValue){
is String -> prefs.getString(key, defValue)
is Int -> prefs.getInt(key, defValue)
is Boolean -> prefs.getBoolean(key, defValue)
is Long -> prefs.getLong(key, defValue)
is Float -> prefs.getFloat(key, defValue)
is Set<*> -> {
if(defValue.isNotEmpty() && defValue.elementAt(0) is String) prefs.getStringSet(key, defValue as Set<String>)
else return null
}
else -> null
}
}
open fun write(key: String, value: Any):Any? {
val prefsEditor: SharedPreferences.Editor = prefs.edit()
with(prefsEditor) {
when(value){
is String -> putString(key, value)
is Int -> putInt(key, value)
is Boolean -> putBoolean(key, value)
is Long -> putLong(key, value)
is Float -> putFloat(key, value)
is Set<*> -> {
if(value.isNotEmpty() && value.elementAt(0) is String) putStringSet(key, value as Set<String>)
else return null
}
else -> return null
}
commit()
}
return value
}
}
然后,在我的特定项目中,我创建一个单例,该单例初始化先前定义的SharedPreference并对给定键进行完整性检查。
import android.content.Context
import androidx.preference.PreferenceManager
import org.albaspazio.core.sharedpreferences.SharedPreferenceWrapper
object PsySuitePreferences: SharedPreferenceWrapper() {
private val validKeys:List<String> = listOf(
"pref_delay_a1", "pref_delay_a2", "pref_delay_a3",
"pref_delay_t1", "pref_delay_t2",
"pref_delay_v1", "pref_delay_v2",
"pref_main_email")
//call it once
fun init(context:Context, pref_name:String="", mode:Int = Context.MODE_PRIVATE){
if(isInitialized()) return // prevent multiple init
prefs = if(pref_name.isEmpty()) PreferenceManager.getDefaultSharedPreferences(context)
else context.getSharedPreferences(pref_name, mode)
}
override fun read(key: String, defValue: Any): Any?{
return if(!validKeys.contains(key) || !isInitialized()) null
else super.read(key, defValue)
}
override fun write(key: String, value: Any): Any?{
return if(!validKeys.contains(key) || !isInitialized()) null
else super.write(key, value)
}
}
ciao