Android의 SharedPreferences에 배열 또는 객체를 추가 할 수 있습니까?


82

나는이 ArrayList이름과 아이콘 포인터를 가지고있는 개체를 나는 그것을에서 저장할 SharedPreferences. 어떻게 할 수 있습니까?

참고 : 데이터베이스를 사용하고 싶지 않습니다.

답변:


59

그래서 데이터 저장소 의 안드로이드 개발자 사이트에서 :

사용자 기본 설정

공유 기본 설정 사용자가 선택한 벨소리와 같은 "사용자 기본 설정"을 저장하기위한 것이 아닙니다 . 애플리케이션에 대한 사용자 기본 설정을 만드는 데 관심이있는 경우 자동으로 유지되는 (공유 기본 설정 사용) 사용자 기본 설정을 만들 수있는 활동 프레임 워크를 제공하는 PreferenceActivity를 참조하세요.

그래서 그냥 지속되는 키-값 쌍이기 때문에 괜찮다고 생각합니다.

원래 포스터에게 이것은 그렇게 어렵지 않습니다. 배열 목록을 반복하고 항목을 추가하기 만하면됩니다. 이 예제에서는 단순성을 위해 맵을 사용하지만 배열 목록을 사용하고 적절하게 변경할 수 있습니다.

// my list of names, icon locations
Map<String, String> nameIcons = new HashMap<String, String>();
nameIcons.put("Noel", "/location/to/noel/icon.png");
nameIcons.put("Bob", "another/location/to/bob/icon.png");
nameIcons.put("another name", "last/location/icon.png");

SharedPreferences keyValues = getContext().getSharedPreferences("name_icons_list", Context.MODE_PRIVATE);
SharedPreferences.Editor keyValuesEditor = keyValues.edit();

for (String s : nameIcons.keySet()) {
    // use the name as the key, and the icon as the value
    keyValuesEditor.putString(s, nameIcons.get(s));
}
keyValuesEditor.commit()

키-값 쌍을 다시 읽으려면 비슷한 작업을 수행합니다. 이것이 작동하는지 알려주십시오.

업데이트 : API 레벨 11 이상을 사용 하는 경우 문자열 세트를 작성 하는 방법 이 있습니다.


감사합니다 Noel, 나는 당신의 코드의 도움으로 그것을 알아 냈습니다. 그래도 코드 오타를 확인하십시오. ;)
zsniperx 2010 년

매력 ... 들으처럼 일
발라 비슈누

74

API 수준에 관계없이 SharedPreferences에서 문자열 배열 및 개체 배열을 확인 합니다.


어레이 저장

public boolean saveArray(String[] array, String arrayName, Context mContext) {   
    SharedPreferences prefs = mContext.getSharedPreferences("preferencename", 0);  
    SharedPreferences.Editor editor = prefs.edit();  
    editor.putInt(arrayName +"_size", array.length);  
    for(int i=0;i<array.length;i++)  
        editor.putString(arrayName + "_" + i, array[i]);  
    return editor.commit();  
} 

로드 어레이

public String[] loadArray(String arrayName, Context mContext) {  
    SharedPreferences prefs = mContext.getSharedPreferences("preferencename", 0);  
    int size = prefs.getInt(arrayName + "_size", 0);  
    String array[] = new String[size];  
    for(int i=0;i<size;i++)  
        array[i] = prefs.getString(arrayName + "_" + i, null);  
    return array;  
}  

9
이것은 끔찍한 기술입니다. 해당 블로그 의 의견 을 참조하십시오 . "이 접근 방식의 문제는 기본 설정을 오염시킬 수 있다는 것입니다. 예를 들어, 100 개의 항목이있는 배열을 저장 한 다음 축소합니다. 2. 기본 설정에 100 개의 항목이 있습니다. 먼저 청소하십시오. "
Kyle Ivey

2
정리하는 것은 오히려 쉽게 추가입니다
보안관 elKhatib

감사합니다. 아주 멋진 스타일의 코드입니다. 이것은 여기에서 내가 가장 좋아하는 답변 중 하나입니다. :)
Martin Pfeffer 2014

3
이것은 잘못된 접근입니다 !!! 100 개의 변수를 추가하려고하는데 이것은 끔찍합니다 !! 대신 jsonarray 및 jsonbj와 함께이 방법을 사용할 수 있습니다. stackoverflow.com/a/8287418/2652368
Amir Hossein Ghasemi

@AmirHosseinGhasemi는 두 가지 접근 방식 모두 실제로 해킹입니다. 감사합니다
Sherif elKhatib 2005

60

쓰기,

SharedPreferences prefs = PreferenceManager
        .getDefaultSharedPreferences(this);
JSONArray jsonArray = new JSONArray();
jsonArray.put(1);
jsonArray.put(2);
Editor editor = prefs.edit();
editor.putString("key", jsonArray.toString());
System.out.println(jsonArray.toString());
editor.commit();

읽다,

try {
    JSONArray jsonArray2 = new JSONArray(prefs.getString("key", "[]"));
    for (int i = 0; i < jsonArray2.length(); i++) {
         Log.d("your JSON Array", jsonArray2.getInt(i)+"");
    }
} catch (Exception e) {
    e.printStackTrace();
}

31

공유 환경 설정 은 API 레벨 11에서 getStringSetputStringSet메소드를 도입 했지만 이전 버전의 Android (여전히 인기)와 호환되지 않으며 문자열 세트로 제한됩니다.

Android는 더 나은 방법을 제공하지 않으며 저장 및로드를 위해 맵과 배열을 반복하는 것은 특히 배열의 경우 매우 쉽고 깔끔하지 않습니다. 그러나 더 나은 구현은 그렇게 어렵지 않습니다.

package com.example.utils;

import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;

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

public class JSONSharedPreferences {
    private static final String PREFIX = "json";

    public static void saveJSONObject(Context c, String prefName, String key, JSONObject object) {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(JSONSharedPreferences.PREFIX+key, object.toString());
        editor.commit();
    }

    public static void saveJSONArray(Context c, String prefName, String key, JSONArray array) {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(JSONSharedPreferences.PREFIX+key, array.toString());
        editor.commit();
    }

    public static JSONObject loadJSONObject(Context c, String prefName, String key) throws JSONException {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        return new JSONObject(settings.getString(JSONSharedPreferences.PREFIX+key, "{}"));
    }

    public static JSONArray loadJSONArray(Context c, String prefName, String key) throws JSONException {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        return new JSONArray(settings.getString(JSONSharedPreferences.PREFIX+key, "[]"));
    }

    public static void remove(Context c, String prefName, String key) {
        SharedPreferences settings = c.getSharedPreferences(prefName, 0);
        if (settings.contains(JSONSharedPreferences.PREFIX+key)) {
            SharedPreferences.Editor editor = settings.edit();
            editor.remove(JSONSharedPreferences.PREFIX+key);
            editor.commit();
        }
    }
}

이제이 다섯 가지 방법을 사용하여 공유 기본 설정에 컬렉션을 저장할 수 있습니다. 작업 JSONObject하고하는 것은 JSONArray매우 쉽습니다. 당신은 사용할 수 있습니다 JSONArray (Collection copyFrom)a를 공공 생성자를 JSONArray자바의 수집 및 이용 아웃 JSONArrayget요소에 액세스하는 방법.

공유 환경 설정에는 크기 제한이 없으므로 (기기의 저장 용량 제한 외에) 이러한 방법은 앱의 일부 컬렉션을 빠르고 쉽게 저장하려는 대부분의 일반적인 경우에 사용할 수 있습니다. 하지만 여기에서 JSON 파싱이 발생하고 Android의 환경 설정은 내부적으로 XML로 저장되므로 메가 바이트의 데이터를 처리 할 때 다른 영구 데이터 저장소 메커니즘을 사용하는 것이 좋습니다.


7
JSON을 사용하는 경우 gson : code.google.com/p/google-gson을 확인하십시오. 자바 객체를 JSON으로 또는 JSON으로 변환합니다.
FeatureCreep 2012

그것은 흥미로운 조합이 될 것입니다.
Mostafa

17

Gson google 라이브러리를 사용하여 복잡한 개체 저장을위한 쉬운 모드 [1]

public static void setComplexObject(Context ctx, ComplexObject obj){
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
    SharedPreferences.Editor editor = preferences.edit();
    editor.putString("COMPLEX_OBJECT",new Gson().toJson(obj)); 
    editor.commit();
}

public static ComplexObject getComplexObject (Context ctx){
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
    String sobj = preferences.getString("COMPLEX_OBJECT", "");
    if(sobj.equals(""))return null;
    else return new Gson().fromJson(sobj, ComplexObject.class);
}

[1] http://code.google.com/p/google-gson/


최상의 것! 이것을 답으로 표시하십시오!
Renan Franca 2014 년

3

아래 코드를 사용하여 내 preferences.xml 파일에 허리 크기 배열 (이미 array.xml에서 생성됨)을로드했습니다. @ array / pant_inch_size는 전체 배열의 ID입니다.

 <ListPreference 
 android:title="choosepantsize"
 android:summary="Choose Pant Size"
 android:key="pantSizePref" 
 android:defaultValue="34" 
 android:entries="@array/pant_inch_size"
 android:entryValues="@array/pant_inch_size" /> 

이로 인해 메뉴가 어레이의 선택 항목으로 채워졌습니다. 기본 크기를 34로 설정 했으므로 메뉴가 표시되면 34가 미리 선택된 것으로 표시됩니다.


Keith 님, 응답 해 주셔서 감사합니다. 주문을 저장해야하고 기본 설정 UI로 작업하지 않으므로 코드가 내가 수행해야하는 작업과 일치하지 않습니다. 어쨌든 감사합니다
zsniperx 2010

아 !! 질문을 잘못 해석했습니다. 죄송합니다. 다른 독자의 경우 내 XML 코드는 단순히 내 array.xml 파일에서 항목을 가져 와서 기본 설정이 "34"로 미리 선택된 상태로 기본 설정 메뉴에로드합니다. 그런 다음 Java를 사용하여 "pantSizePref"( "키")라는 특정 환경 설정에 대한 식별자를 찾습니다.
Keith

2

간단한 방법은 아래 예제와 같이 JSON 문자열로 변환하는 것입니다.

Gson gson = new Gson();
String json = gson.toJson(myObj);

그런 다음 공유 기본 설정에 문자열을 저장합니다. 필요한 경우 공유 환경 설정에서 문자열을 가져 와서 JSONArray 또는 JSONObject로 다시 변환하십시오 (요구 사항에 따라).


2

쓰기 :

 private <T> void storeData(String key, T data) {
    ByteArrayOutputStream serializedData = new ByteArrayOutputStream();

    try {
        ObjectOutputStream serializer = new ObjectOutputStream(serializedData);
        serializer.writeObject(data);
    } catch (IOException e) {
        e.printStackTrace();
    }

    SharedPreferences sharedPreferences = getSharedPreferences(TAG, 0);
    SharedPreferences.Editor edit = sharedPreferences.edit();

    edit.putString(key, Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT));
    edit.commit();
}

읽기 :

private <T> T getStoredData(String key) {
    SharedPreferences sharedPreferences = getSharedPreferences(TAG, 0);
    String serializedData = sharedPreferences.getString(key, null);
    T storedData = null;
    try {
        ByteArrayInputStream input = new ByteArrayInputStream(Base64.decode(serializedData, Base64.DEFAULT));
        ObjectInputStream inputStream = new ObjectInputStream(input);
        storedData = (T)inputStream.readObject();
    } catch (IOException|ClassNotFoundException|java.lang.IllegalArgumentException e) {
        e.printStackTrace();
    }

    return storedData;
}

이것은 건전한 제안처럼 보입니다. 공통 컬렉션은 모두 직렬화 가능을 구현하며 기본 문자열, 숫자 및 날짜는 직렬화 가능합니다. 유일한 단점은 성능입니다.
androidguy

1

이것은 내가 성공적으로 사용하는 공유 환경 설정 코드입니다 . 다음 링크를 참조하십시오 .

  public class MainActivity extends Activity {

private static final int RESULT_SETTINGS = 1;
Button button;
public String a="dd";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

 button = (Button) findViewById(R.id.btnoptions);


setContentView(R.layout.activity_main);

  // showUserSettings();
  }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.settings, menu);
return true;
 }

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {

case R.id.menu_settings:
 Intent i = new Intent(this, UserSettingActivity.class);
 startActivityForResult(i, RESULT_SETTINGS);
 break;

 }

return true;
}

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data)     {
  super.onActivityResult(requestCode, resultCode, data);

 switch (requestCode) {
 case RESULT_SETTINGS:
 showUserSettings();
 break;

 } 

  }

  private void showUserSettings() {
 SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);

 StringBuilder builder = new StringBuilder();

 builder.append("\n Pet: "
  + sharedPrefs.getString("prefpetname", "NULL"));

 builder.append("\n Address:"
 + sharedPrefs.getString("prefaddress","NULL" ));

 builder.append("\n Your name: "
 + sharedPrefs.getString("prefname", "NULL"));

 TextView settingsTextView = (TextView) findViewById(R.id.textUserSettings);


  settingsTextView.setText(builder.toString());


    }

   }

즐거운 코딩!


0

putStringSet 을 사용할 수 있습니다.

이렇게하면 다음과 같이 기본 설정에 HashSet을 저장할 수 있습니다.

저장

Set<String> values;

SharedPreferences sharedPref = 
    mContext.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);

Editor editor = sharedPref.edit();

editor.putStringSet("YOUR_KEY", values);
editor.apply();

검색

SharedPreferences sharedPref = 
    mContext.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);

Editor editor = sharedPref.edit();

Set<String> newList = editor.getStringSet("YOUR_KEY", null);

putStringSet은 Set 만 허용하며 이것은 정렬되지 않은 목록입니다.


0

이 문제로 버그가 발생했을 때 문자열을 직렬화 할 수있는 직렬화 솔루션을 얻었지만 해킹도 생각해 냈습니다.

직렬화에 대해 읽지 않은 경우에만 이것을 읽으십시오. 그렇지 않으면 아래로 가서 내 해킹을 읽으십시오.

배열 항목을 순서대로 저장하기 위해 배열을 단일 문자열로 직렬화 할 수 있습니다 (새 클래스 ObjectSerializer를 만들어서 (– www.androiddevcourse.com/objectserializer.html에서 코드 복사, 패키지 이름을 제외한 모든 항목 교체))

공유 환경 설정에 데이터 입력 : 여기에 이미지 설명 입력

38 행의 나머지 코드- 여기에 이미지 설명 입력

다음 인자를 이것으로 넣으면 데이터가 검색되지 않으면 빈 배열이 반환됩니다 (빈 문자열을 넣을 수 없습니다. coz 컨테이너 / 변수는 문자열이 아닌 배열입니다)

내 해킹에오고 :-

각 항목 사이에 기호를 넣어 배열의 내용을 단일 문자열로 병합 한 다음 검색 할 때 해당 기호를 사용하여 분할합니다. Coz 추가 및 검색 문자열은 공유 환경 설정으로 쉽습니다. 분할이 걱정된다면 "자바에서 문자열 분할"을 찾아보십시오.

[참고 : 이것은 배열의 내용이 string, int, float 등과 같은 원시적 인 종류 인 경우 잘 작동합니다. 자체 구조를 가진 복잡한 배열에 대해 작동합니다. 전화 번호부라고 가정하면 병합 및 분할은 조금 복잡합니다. ]

추신 : 나는 안드로이드를 처음 접하기 때문에 그것이 좋은 해킹인지 모르겠습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.