마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

쉐어드 프리퍼런스 (SharedPreferences) 질문입니다

0 추천
.

SharedPreferences에서 키값이 같은데 데이터 타입은 달라도 문제없을까요?

예를들면

mSP.getBoolean("키값A", false);

mSP.getInt("키값A", 0);

mEditor.putBoolean("키값A", true);

mEditor.putInt("키값A", mSP.getInt("키값A", 0)).commit();

(참고로 mSP = SharedPreferences,   mEditor = SharedPreferences.Editor)

위와 같은 경우가 가능할까요?

.
abchs8wyw (1,710 포인트) 님이 2020년 12월 23일 질문

2개의 답변

+1 추천
get/put시 type을 일관되게 유지해 주세요.

SharedPreferences는 xml 형식으로 저장되고 저장시 value의 type도 같이 저장되고 읽어들일 때 그 type에 맞게 Boolean, Long, Int 등의 객체로 읽어들이게 됩니다.

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/com/android/internal/util/XmlUtils.java#640

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/com/android/internal/util/XmlUtils.java#1522
익명사용자 님이 2020년 12월 24일 답변
0 추천

SharedPreferences가 어차피 XML 파일에 저장되므로 모든 건 String으로 저장됩니다. 겱국 제공하는 API를 사용하더라도 확실하게 타입에 안전하지는 않습니다. 그래서 모든 걸 String으로 저장하고 읽어오거나 JSON으로 변환해서 처리하는 등의 처리가 가능합니다. 다른 분 말씀처럼, 타입을 일관되게 사용하는 게 정말  좋지만, 만약 타입이 다른데 다른 타입을 써야 하는 경우라면,
원시타입일 경우는 String으로, object일 경우는 JSON으로 저장해서 처리할 수도 있습니다. JSON으로 저장하고 읽어온다면 어떤 값이든 읽어올 수는 있겠죠.

테스트는 안해봤지만, 아래처럼 할 수 있을 것 같다는 생각이 듭니다.

public class TypedValue<T> {
    private final T value;

    public TypedValue(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

public class TypedValuePreferences {

    public static final String KEY_TYPED_VALUE = "KEY_TYPED_VALUE";

    private final SharedPreferences prefs;
    private final Gson gson;
    public TypedValueStore(SharedPreferences prefs, Gson gson) {
        this.prefs = prefs;
        this.gson = gson;
    }

    public <T> void putTypedValue(TypedValue<T> value) {
        Type typedValueType = new TypeToken<TypedValue<T>>() {
        }.getType();
        String jsonString = gson.toJson(value, typedValueType);
        prefs.edit()
                .putString(KEY_TYPED_VALUE, jsonString)
                .apply();
    }

    public <T> TypedValue<T> getTypedValue(String key, Class<T> tClass) {
        Type typedValueType = new TypeToken<TypedValue<T>>() {
        }.getType();
        try {
            String jsonString = prefs.getString(KEY_TYPED_VALUE, "");
            return gson.fromJson(jsonString, typedValueType);
        } catch (JsonSyntaxException e) {
            return new TypedValue<T>(null);
        }
    }
    
}

하지만, 더 좋은 접근 방법은 다른 분 말씀처럼, 타입을 정확하게 지키는 것이겠죠.

spark (226,720 포인트) 님이 2020년 12월 24일 답변
...