使用SharedPreferences的最安全的方法

时间:2016-10-14 09:13:30

标签: java android singleton sharedpreferences preferences

我需要一个处理我的SharedPreferences的类,我想出了3种方法,但经过一些研究后,似乎大多数都被认为是“反模式”。

输入1

public final class MyPrefs {

  private MyPrefs(){ throw new AssertionError(); }

  public static void setFavoriteColor(Context context, String value){
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    prefs.edit().putString("color_key", value).apply();
  }

  public static void setFavoriteAnimal(Context context, String value){
    // ...
  }

  // ...

}

/* Usage */
MyPrefs.setFavoriteColor(this, "yellow");

// Reason why it might be considered "Bad"
// Class is not OO, just collection of static methods. "Utility Class"

类型2

public class MyPrefs {

  private SharedPreferences mPreferences;
  private static volatile MyPrefs sInstance; 

  public static MyPrefs getInstance(Context context){
    if(sInstance == null){
      synchronized(MyPrefs.class){
        if(sInstance == null){
          sInstance = new MyPrefs(context);
        }
      }
    }
    return sInstance;
  }

  private MyPrefs(Context context){ 
    mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
  }

  public void setFavoriteColor(String value){
    mPreferences.edit().putString("color_key", value).apply();
  }

  public void setFavoriteAnimal(Context context, String value){
    // ...
  }

  // ...

}

/* Usage */
MyPrefs myPrefs = MyPrefs.getInstance(this);
myPrefs.setFavoriteColor("red");


// Reason why it might be considered "Bad"
// Singleton's are frowned upon especially
// in android because they can cause problems and unexpected bugs.

类型3

public class MyPrefs {

  SharedPreferences mPreferences;

  public MyPrefs(Context context){ 
    mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
  }

  public void setFavoriteColor(String value){
    mPreferences.edit().putString("color_key", value).apply();
  }

  public void setFavoriteAnimal(Context context, String value){
    // ...
  }

  // ...

}

/* Usage */
MyPrefs myPrefs = new MyPrefs(this);
myPrefs.setFavoriteColor("green");

// Reason why it might be considered "Bad"
// Lots of boilerplate and must create object every 
// time you want to save a preference.

现在我的首选包装器显然不仅包含2个setter,它们有很多getter和setter在保存值之前进行一些边处理,因此在主要活动中保存和处理首选项会导致很多凌乱的代码和错误。

现在,哪些方法不会对性能造成负面影响/导致意外错误?

5 个答案:

答案 0 :(得分:5)

  

类型1: -

在类型1 中,您直接使用此class method,这个最好........

  

类型2: -

在类型2 中,有一个Static Variable 导致您应用中的MemoryLeakException。如果您想使用类型2,那么每当您使用此类时,您都会将INSTANCE变量设为null(这些可以解决MemoryLeakException 的问题)..... ..

  

类型3: -

在类型3 中,您必须创建Heap Memory(将RAM内存用于实例,直到其范围结束) new Instance类,无论何时你想使用这个类。如果您必须在单class methods中多次使用此Activity,那么此课程将有所帮助.......

  

使用此类简单使用SharePrefernce .....

public class Utility {

    public static boolean getBoolean(Context context, String key) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getBoolean(key, false);
    }

    public static String getString(Context context, String key) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(key, "");
    }

    public static int getInt(Context context, String key) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getInt(key, -1);
    }


    public static void setString(Context context, String key, String value) {
        PreferenceManager.getDefaultSharedPreferences(context).edit().putString(key, value).commit();
    }

    public static void setBoolean(Context context, String key, boolean value) {
        PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(key, value).commit();
    }


}
  

用于设置字符串....

Utility.setString(this,"token","your token");
  

并获取字符串......

Utility.getString(this,"token");

注意: - 在此条款中,您无需创建任何 Heap Memory OR Static Variable.

答案 1 :(得分:2)

在您的项目中包含此类,并且只要您想在SharedPreferences中设置某些内容,然后在类名称和传递参数的帮助下使用该函数。您的任务很简单,您只需编写一行代码即可保存并从共享PReference中获取任何值。

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

public class SharedPrefManager {

    public static SharedPreferences getSharedPref(Context mContext) {
        SharedPreferences pref = mContext.getSharedPreferences(Constants.SETTINGS, Context.MODE_PRIVATE);

        return pref;
    }

    public static void setPrefVal(Context mContext, String key, String value) {
        if(key!=null){
        Editor edit = getSharedPref(mContext).edit();
        edit.putString(key, value);
        edit.commit();
        }
    }

    public static void setIntPrefVal(Context mContext, String key, int value) {
        if(key!=null){
            Editor edit = getSharedPref(mContext).edit();
            edit.putInt(key, value);
            edit.commit();
        }
    }

    public static void setLongPrefVal(Context mContext, String key, Long value) {
        if(key!=null){
            Editor edit = getSharedPref(mContext).edit();
            edit.putLong(key, value);
            edit.commit();
        }
    }

    public static void setBooleanPrefVal(Context mContext, String key, boolean value) {
        if(key!=null){
            Editor edit = getSharedPref(mContext).edit();
            edit.putBoolean(key, value);
            edit.commit();
        }
    }


    public static String getPrefVal(Context mContext, String key) {
        SharedPreferences pref = getSharedPref(mContext);
        String val = "";
        try {
            if (pref.contains(key))
                val = pref.getString(key, "");
            else
                val = "";
        }catch (Exception e){
            e.printStackTrace();
        }
        return val;
    }

    public static int getIntPrefVal(Context mContext, String key) {
        SharedPreferences pref = getSharedPref(mContext);
        int val = 0;
        try {
        if(pref.contains(key)) val = pref.getInt(key, 0);
        }catch (Exception e){
            e.printStackTrace();
        }
        return val;
    }

    public static Long getLongPrefVal(Context mContext, String key) {
        SharedPreferences pref = getSharedPref(mContext);
        Long val = null;
        try{
        if(pref.contains(key)) val = pref.getLong(key, 0);
    }catch (Exception e){
        e.printStackTrace();
    }
        return val;
    }

    public static boolean getBooleanPrefVal(Context mContext, String key) {
        SharedPreferences pref = getSharedPref(mContext);
        boolean val = false;
        try{
        if(pref.contains(key)) val = pref.getBoolean(key, false);

        }catch (Exception e){
            e.printStackTrace();
        }
        return val;
    }


    public static boolean containkey(Context mContext,String key)
    {
        SharedPreferences pref = getSharedPref(mContext);
        return pref.contains(key);
    } 


}

答案 2 :(得分:1)

public class Prefs {
private static final String KEY_TOKEN = "token";
private final SharedPreferences m_prefsRead;
private final SharedPreferences.Editor m_prefsWrite;

public Prefs(Context context) {
    final String PREFS = "Sample";
    m_prefsRead = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
    m_prefsWrite = m_prefsRead.edit();
}

public String getToken() {
    return m_prefsRead.getString(KEY_TOKEN, null);
}

public void setToken(String accessToken) {
    m_prefsWrite.putString(KEY_TOKEN, accessToken);
    m_prefsWrite.commit();
}

}

在应用程序文件中初始化Prefs:

public class MyApp extends Application {
private static MyApp m_instance;
private Prefs m_prefs;

    @Override
    public void onCreate() {
        super.onCreate();
        m_instance = this;

        m_prefs = new Prefs(this);
    }

    public static MyApp getInstance() {
        return m_instance;
    }

     public Prefs getPrefs() {
        return m_prefs;
    }
}

我们可以使用以下任意方式访问Prefs: 。MyApp.getInstance()getPrefs()为gettoken();

答案 3 :(得分:1)

看看这个article。一切都被清楚地描述,并考虑了最佳实践。文章中的代码:

    public class PreferencesManager {

    private static final String PREF_NAME = "com.example.app.PREF_NAME";
    private static final String KEY_VALUE = "com.example.app.KEY_VALUE";

    private static PreferencesManager sInstance;
    private final SharedPreferences mPref;

    private PreferencesManager(Context context) {
        mPref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
    }

    public static synchronized void initializeInstance(Context context) {
        if (sInstance == null) {
            sInstance = new PreferencesManager(context);
        }
    }

    public static synchronized PreferencesManager getInstance() {
        if (sInstance == null) {
            throw new IllegalStateException(PreferencesManager.class.getSimpleName() +
                    " is not initialized, call initializeInstance(..) method first.");
        }
        return sInstance;
    }

    public void setValue(long value) {
        mPref.edit()
                .putLong(KEY_VALUE, value)
                .commit();
    }

    public long getValue() {
        return mPref.getLong(KEY_VALUE, 0);
    }

    public void remove(String key) {
        mPref.edit()
                .remove(key)
                .commit();
    }

    public boolean clear() {
        return mPref.edit()
                .clear()
                .commit();
    }
}

但您可以根据自己的目的进行修改。实际上我没有看到任何不好的东西,因为有一个Singleton会处理所有的sharedprefs操作。当然,您可以使用静态方法创建Util类,使用不同版本的单例模式,甚至直接使用PreferencesManager(BTW它也是单例)。就个人而言,我更喜欢单身方法。

答案 4 :(得分:0)

嘿,我使用了偏好设置,这段代码似乎对我来说最好!易于维护,您可以自定义,并添加加密,例如;)。

在本课程" MyPref"您可以自定义存储在您偏好中的数据类型。

public class MyPref implements SharedPreferences {
private SharedPreferences sharedPreferences;


public MyPref(Context context, final String sharedPrefFilename) {
    if (sharedPreferences == null) {
        sharedPreferences = getSharedPreferenceFile(context, sharedPrefFilename);
    }
}

private SharedPreferences getSharedPreferenceFile(Context context, String prefFilename) {
    if (TextUtils.isEmpty(prefFilename)) {
        return PreferenceManager
                .getDefaultSharedPreferences(context);
    } else {
        return context.getSharedPreferences(prefFilename, Context.MODE_PRIVATE);
    }
}

//----- SHARED PREFERENCES INTERFACE----
@Override
public Map<String, ?> getAll() {
    return sharedPreferences.getAll();
}

@Override
public String getString(String s, String s1) {
    return sharedPreferences.getString(s,s1);
}

@Override
public Set<String> getStringSet(String s, Set<String> set) {
    return sharedPreferences.getStringSet(s,set);
}

@Override
public int getInt(String s, int i) {
    return sharedPreferences.getInt(s,i);
}

@Override
public long getLong(String s, long l) {
    return sharedPreferences.getLong(s,l);
}

@Override
public float getFloat(String s, float v) {
    return sharedPreferences.getFloat(s,v);
}

@Override
public boolean getBoolean(String s, boolean b) {
    return sharedPreferences.getBoolean(s,b);
}

@Override
public boolean contains(String s) {
    return sharedPreferences.contains(s);
}

@Override
public Editor edit() {
    return new MyEditor();
}


@Override
public void registerOnSharedPreferenceChangeListener(
        OnSharedPreferenceChangeListener listener) {
    sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
}

@Override
public void unregisterOnSharedPreferenceChangeListener(
        OnSharedPreferenceChangeListener listener) {
    sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
}

/**
 * Inner class implements the Preference editor ,this class is responsible of preference editing (you can add encryption here).
 */
    class MyEditor implements SharedPreferences.Editor {

    private SharedPreferences.Editor mEditor;

    private MyEditor() {
        mEditor = sharedPreferences.edit();
    }

    @Override
    public Editor putString(String s, String s1) {
        mEditor.putString(s,s1);
        return this;
    }

    @Override
    public Editor putStringSet(String s, Set<String> set) {
        mEditor.putStringSet(s,set);
        return this;
    }

    @Override
    public Editor putInt(String s, int i) {
        mEditor.putInt(s,i);
        return this;
    }

    @Override
    public Editor putLong(String s, long l) {
        mEditor.putLong(s,l);
        return this;
    }

    @Override
    public Editor putFloat(String s, float v) {
        mEditor.putFloat(s,v);
        return this;
    }

    @Override
    public Editor putBoolean(String s, boolean b) {
        mEditor.putBoolean(s,b);
        return this;
    }

    @Override
    public Editor remove(String s) {
        mEditor.remove(s);
        return this;
    }

    @Override
    public Editor clear() {
        mEditor.clear();
        return this;
    }

    @Override
    public boolean commit() {
        return mEditor.commit();
    }

    @Override
    public void apply() {
        mEditor.apply();
    }
    }
}

在本课程中,您只需添加Key&amp; Getter和Setter

public class Pref {

private static final String MY_KEY1 = "MY_KEY1";
private static final String MY_KEY2 = "MY_KEY2";
private static final String MY_KEY3 = "MY_KEY3";

private static final String PREF_FILENAME = "MY_PREF_FILENAME";

private static SharedPreferences getSharedPreferences(Context context) {
    return new MyPref(context , PREF_FILENAME);
}

private static SharedPreferences.Editor getEditor(Context context) {
    return getSharedPreferences(context)
            .edit();
}

/*  You have just to ADD you KEY & Getter and Setter*/
public static void putKey1(Context context, String date) {
    getEditor(context).putString(MY_KEY1, date).apply();
}

public static String getKey1(Context context) {
    return getSharedPreferences(context).contains(MY_KEY1) ?
            getSharedPreferences(context).getString(MY_KEY1, null) :
            null;
}
public static void putKey2(Context context, String date) {
    getEditor(context).putString(MY_KEY1, date).apply();
}

public static String getKey2(Context context) {
    return getSharedPreferences(context).contains(MY_KEY2) ?
            getSharedPreferences(context).getString(MY_KEY2, null) :
            null;
}
public static void putKey3(Context context, String date) {
    getEditor(context).putString(MY_KEY1, date).apply();
}

public static String getKey3(Context context) {
    return getSharedPreferences(context).contains(MY_KEY3) ?
            getSharedPreferences(context).getString(MY_KEY3, null) :
            null;
}

}

使用:

public class MainActivity extends Activity {
TextView hello;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Pref.putKey1(this,"HELLO FROM PREFS");

    hello = (TextView) findViewById(R.id.hello);
    hello.setText(Pref.getKey1(this));
}
}