2016-10-14 61 views
14

Potrzebuję klasy, która obsługuje moje SharedPreferences i wymyśliłem 3 sposoby na zrobienie tego, jednak po pewnych badaniach wydaje się, że większość z nich jest uważana za "anti-patterns".Najbezpieczniejszy sposób korzystania z SharedPreferences

Type 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" 

Type 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. 

Type 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. 

Teraz moje preferencji owijarki oczywiście nie składa się tylko z 2 ustawiaczy, mają wiele pobierające i setery, które wykonują pewne przetwarzanie boczne przed zapisaniem wartości, więc mając preferencje zapisane i przetworzone w ramach th Główna działalność spowodowałaby wiele bałaganu i błędów.

Teraz, które z tych podejść nie będą miały negatywnego wpływu na wydajność/powodować nieoczekiwane błędy?

+0

to ty problem został rozwiązany? –

+0

@SumitYadav tak prawie. Wygląda na to, że wszystkie działają i można ich bezpiecznie używać, jednak niektóre (np. Singleton) mogą powodować problemy, z którymi trzeba się uporać. Po prostu pozostanę bezpieczny i użyję 1 lub 3. – Linxy

+0

Nie używaj metody .apply(), używaj metody .commit() w osobnym wątku. Powodem jest to, że .apply() planuje zapisywanie w tle i nie możesz być pewien, że dane są zapisywane przed innym .apply(). Może to spowodować utratę danych. Zamiast tego użyj .commit(), powiedzmy, w łańcuchu rxJava: –

Odpowiedz

5

Typ 1: -

W typie 1, można bezpośrednio skorzystać z tej class method, ten jest najlepszy ........

Typ 2: -

w typie 2 jest jedna Static Variable, który będzie przyczyną the w twojej aplikacji. Jeśli chcesz użyć typu 2 wtedy dokonaniu INSTANCE zmienną wartość null, gdy używasz tej klasy (te można rozwiązać problem MemoryLeakException) .......

Typ 3: -

W typie 3, trzeba stworzyć Heap Memory (wziąć pamięć RAM na przykład aż do końca zakresu) Albonew Instance z klasy, gdy chcesz korzystać z tej klasy. Podklasa ta nie pomoże, jeśli trzeba to wykorzystać class methods w wielu czasie w pojedynczym Activity .......

użycie tej klasy do prostego stosowania 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(); 
    } 


} 

na ustawienie ciąg ....

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

i za pobranie ciągu ...

Utility.getString(this,"token"); 

Uwaga: - W tej kla, nie trzeba tworzyć żadnychHeap Memory OR Static Variable.

+1

Ta odpowiedź jest podejrzana, ponieważ 1) Nie ma nic złego w przechowywaniu statycznego odniesienia do SharedPreferences i 2) Nie ma czegoś takiego jak "MemoryLeakException" –

+0

Czy to jest ' prywatna statyczna zmienność MyPrefs sInstance; 'zmienna nie powodująca' MemoryLeakException'. Czytam wiele blogów, na których ludzie mówią używając zmiennej statycznej powodującej 'MemoryLeakException' przechodzą przez ten http://stackoverflow.com/a/39694463/5305430. Jeśli potrzebujesz więcej bloga, daj mi znać? – sushildlh

+0

Myślę, że masz na myśli 'OutOfMemoryException'? Występują one, gdy zużywasz zbyt dużo pamięci, a Twoja aplikacja nie może przydzielić więcej pamięci, kiedy zajdzie taka potrzeba. SharedPreferences jest już obiektem pojedynczym, a przechowywanie statycznego odwołania do niego nie zwiększy twojego śladu pamięci. Można znaleźć wiele przykładów na SO pojedynczych wrapperów dla SharedPreferences. Referencje singleton są odniesieniami statycznymi. –

2

Uwzględnij tę klasę w projekcie i kiedy chcesz ustawić coś w SharedPreferences następnie użyć funkcji za pomocą nazw klas i parametrów przebiegu. Twoje zadanie będzie proste i po prostu musisz napisać pojedynczą linię kodu, aby zapisać i uzyskać dowolną wartość z Shared 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); 
    } 


} 
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(); 
} 

}

zainicjować Preferencje w pliku danych:

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; 
    } 
} 

Możemy dostęp Prefs gdziekolwiek przez cały aplikacji za pomocą:. MyApp.getInstance() getPrefs() .getToken();

1

Spójrz na to article. Wszystko jest jasno opisane, a najlepsze praktyki są brane pod uwagę. Kod z artykułu:

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(); 
    } 
} 

Ale można go modyfikować w zależności od celów. Właściwie nie widzę niczego złego, mając Singleton, który obsłuży wszystkie operacje sharedprefs. Zdecydowanie można utworzyć klasę Util za pomocą metod statycznych, użyć różnych wersji wzorca singleton lub nawet użyć bezpośrednio PreferencesManager (BTW to także singleton). Osobiście wolę podejście singletonowe.

+0

Odpowiedzi nie powinny składać się z linku do artykułu, który może się w przyszłości zepsuć. –

+0

Roger to, szefie! –

0

Hej, pracowałem dużo z Preferencjami i ten kod wydaje mi się najlepszy! łatwa w utrzymaniu, można ją dostosować i na przykład dodać szyfrowanie;).

w tej klasie "MyPref" można dostosować typ danych przechowywanych w preferencjach użytkownika.

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(); 
    } 
    } 
} 

w tej klasie trzeba po prostu dodać klucz & Getter i 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; 
} 

} 

przeznaczenie:

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)); 
} 
}