Có thể thêm mảng hoặc đối tượng vào SharedPreferences trên Android không


82

Tôi có một ArrayListtrong số các đối tượng có tên và con trỏ biểu tượng và tôi muốn lưu nó vào SharedPreferences. Làm thế nào tôi có thể làm được?

LƯU Ý: Tôi không muốn sử dụng Cơ sở dữ liệu

Câu trả lời:


59

Vì vậy, từ trang web dành cho nhà phát triển Android trên Data Storage :

Sở thích của người sử dụng

Tùy chọn chia sẻ không hoàn toàn để lưu "tùy chọn người dùng", chẳng hạn như nhạc chuông mà người dùng đã chọn. Nếu bạn quan tâm đến việc tạo tùy chọn người dùng cho ứng dụng của mình, hãy xem PreferenceActivity, cung cấp khung Hoạt động để bạn tạo tùy chọn người dùng, tùy chọn này sẽ tự động tồn tại (sử dụng tùy chọn được chia sẻ).

Vì vậy, tôi nghĩ rằng nó không sao vì nó chỉ đơn giản là các cặp khóa-giá trị được duy trì.

Đối với người đăng ban đầu, điều này không khó lắm. Bạn chỉ cần lặp lại danh sách mảng của mình và thêm các mục. Trong ví dụ này, tôi sử dụng bản đồ để đơn giản hóa nhưng bạn có thể sử dụng danh sách mảng và thay đổi nó một cách thích hợp:

// 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()

Bạn sẽ làm điều gì đó tương tự để đọc lại các cặp khóa-giá trị. Hãy cho tôi biết nếu các công trình này.

Cập nhật: Nếu bạn đang sử dụng API cấp 11 trở lên, có một phương pháp để ghi ra Tập hợp chuỗi


Cảm ơn Noel, tôi đã tìm ra nó với sự giúp đỡ của mã của bạn. Xem các lỗi chính tả mã. ;)
zsniperx

Làm việc như một nét duyên dáng ... Thx
Bala Vishnu

74

Bất kể cấp API là gì, hãy kiểm tra mảng chuỗi và mảng đối tượng trong SharedPreferences


LƯU ĐẾN

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

TẢI ĐẾN

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
Đây là một kỹ thuật khủng khiếp. Xem các nhận xét trên blog đó: "Vấn đề với cách tiếp cận này là bạn sẽ làm ô nhiễm các tùy chọn của mình. Giả sử, bạn lưu một mảng có 100 mục nhập và sau đó thu nhỏ lại. 2. Bạn sẽ vẫn có 100 mục nhập trong tùy chọn của mình trừ khi bạn hãy dọn dẹp nó trước. "
Kyle Ivey

2
Dọn dẹp là khá một sự bổ sung dễ dàng
Sherif elKhatib

Cảm ơn, mã kiểu cách rất đẹp. Đây là một trong những câu trả lời yêu thích của tôi ở đây trên SO. :)
Martin Pfeffer

3
Đây là một cách tiếp cận sai lầm !!! bạn thử thêm 100 biến, và điều này thật khủng khiếp !! thay vào đó, bạn có thể sử dụng phương pháp này với jsonarray và jsonbj: stackoverflow.com/a/8287418/2652368
Amir Hossein Ghasemi

@AmirHosseinGhasemi cả hai cách tiếp cận đều thực sự là hack. cảm ơn
Sherif elKhatib

60

Viết,

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

Đọc,

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

Tùy chọn chia sẻ đã giới thiệu a getStringSetputStringSetcác phương thức trong API Cấp 11, nhưng điều đó không tương thích với các phiên bản Android cũ hơn (vẫn còn phổ biến) và cũng bị giới hạn ở các nhóm chuỗi.

Android không cung cấp các phương pháp tốt hơn và việc lặp lại các bản đồ và mảng để lưu và tải chúng không dễ dàng và sạch sẽ, đặc biệt là đối với mảng. Nhưng triển khai tốt hơn không quá khó:

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

Giờ đây, bạn có thể lưu bất kỳ bộ sưu tập nào trong tùy chọn chia sẻ bằng năm phương pháp này. Làm việc với JSONObjectJSONArrayrất dễ dàng. Bạn có thể sử dụng hàm tạo JSONArray (Collection copyFrom)công khai để tạo JSONArrayra từ bất kỳ bộ sưu tập Java nào và sử dụng JSONArraycác getphương thức của để truy cập các phần tử.

Không có giới hạn kích thước cho các tùy chọn chia sẻ (ngoài giới hạn bộ nhớ của thiết bị), vì vậy các phương pháp này có thể hoạt động trong hầu hết các trường hợp thông thường khi bạn muốn lưu trữ nhanh chóng và dễ dàng cho một số bộ sưu tập trong ứng dụng của mình. Nhưng phân tích cú pháp JSON xảy ra ở đây và các tùy chọn trong Android được lưu trữ dưới dạng XML trong nội bộ, vì vậy tôi khuyên bạn nên sử dụng các cơ chế lưu trữ dữ liệu liên tục khác khi bạn đang xử lý megabyte dữ liệu.


7
Nếu bạn đang sử dụng JSON, có thể xem gson: code.google.com/p/google-gson - nó chuyển đổi các đối tượng java thành và từ JSON.
năngCreep vào

Đó sẽ là một sự kết hợp thú vị.
Mostafa

17

Chế độ dễ dàng để lưu trữ đối tượng phức tạp với việc sử dụng thư viện 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/


Tốt nhất! Đánh dấu đây là TRẢ LỜI!
Renan Franca

3

Tôi đã tải một loạt các kích thước vòng eo (đã được tạo trong array.xml của tôi) vào tệp tùy chọn.xml với mã bên dưới. @ array / pant_inch_size là id của toàn bộ mảng.

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

Điều này điền vào menu với các lựa chọn từ mảng. Tôi đặt kích thước mặc định là 34, vì vậy khi menu bật lên, họ thấy kích thước 34 đã được chọn trước.


Xin chào Keith, cảm ơn bạn đã phản hồi. Tôi cần lưu trữ một đơn đặt hàng và tôi không làm việc với tùy chọn ưu tiên nên tôi không thấy rằng mã của bạn khớp với những gì tôi cần hoàn thành. Dù sao cũng cảm ơn
zsniperx

Ah!! Tôi đã hiểu sai câu hỏi của bạn, xin lỗi về điều đó. Đối với bất kỳ trình đọc nào khác, mã XML của tôi chỉ cần lấy các mục từ tệp array.xml của tôi và tải chúng vào menu tùy chọn, với tùy chọn mặc định được chọn trước là "34" trong trường hợp này. Sau đó, tôi sử dụng java để tìm mã định danh cho tùy chọn cụ thể này, đó là "pantSizePref" ("khóa").
Keith

2

Cách đơn giản là chuyển nó thành Chuỗi JSON như ví dụ dưới đây:

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

Sau đó, lưu trữ chuỗi trong tùy chọn được chia sẻ. Khi bạn cần nó, chỉ cần lấy chuỗi từ các tùy chọn được chia sẻ và chuyển đổi trở lại JSONArray hoặc JSONObject (theo yêu cầu của bạn.)


2

Để viết:

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

Để đọc:

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

Đây có vẻ như là một gợi ý âm thanh. Tất cả các bộ sưu tập chung đều triển khai Serializable và Chuỗi, Số và Ngày cơ bản của bạn có thể Serializable. Nhược điểm duy nhất sẽ là hiệu suất.
androidguy

1

Đây là mã ưu đãi được chia sẻ mà tôi sử dụng thành công, Tham khảo liên kết này :

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


    }

   }

GIẢI MÃ VUI VẺ!


0

Bạn có thể sử dụng putStringSet

Điều này cho phép bạn lưu HashSet theo sở thích của mình, giống như sau:

Tiết kiệm

Set<String> values;

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

Editor editor = sharedPref.edit();

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

Retrive

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

Editor editor = sharedPref.edit();

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

PutStringSet chỉ cho phép một Set và đây là một danh sách không có thứ tự .


0

Khi tôi bị lỗi này, tôi đã nhận được giải pháp tuần tự hóa ở đó, bạn có thể tuần tự hóa chuỗi của mình, Nhưng tôi cũng nghĩ ra một cách hack.

Chỉ đọc phần này nếu bạn chưa đọc về việc đăng nhiều kỳ, nếu không hãy đi xuống và đọc bản hack của tôi

Để lưu trữ các mục mảng theo thứ tự, chúng ta có thể tuần tự hóa mảng thành một chuỗi duy nhất (bằng cách tạo một lớp mới ObjectSerializer (sao chép mã từ - www.androiddevcourse.com/objectserializer.html, thay thế mọi thứ ngoại trừ tên gói))

Nhập dữ liệu trong Tùy chọn chia sẻ: nhập mô tả hình ảnh ở đây

phần còn lại của mã trên dòng 38 - nhập mô tả hình ảnh ở đây

Đặt đối số tiếp theo như thế này, để nếu dữ liệu không được truy xuất, nó sẽ trả về mảng trống (chúng tôi không thể đặt chuỗi trống vì vùng chứa / biến là một mảng không phải là chuỗi)

Đến với Hack của tôi: -

Hợp nhất nội dung của mảng thành một chuỗi duy nhất bằng cách có một số ký hiệu ở giữa mỗi mục và sau đó chia nó bằng cách sử dụng ký hiệu đó khi truy xuất nó. Coz thêm và truy xuất Chuỗi dễ dàng với các tùy chọn được chia sẻ. Nếu bạn lo lắng về việc chia nhỏ chỉ cần tra cứu "tách một chuỗi trong java".

[Lưu ý: Điều này hoạt động tốt nếu nội dung của mảng của bạn thuộc loại nguyên thủy như string, int, float, v.v. Nó sẽ hoạt động đối với các mảng phức tạp có cấu trúc riêng của nó, giả sử là danh bạ điện thoại, nhưng việc hợp nhất và tách sẽ trở thành hơi phức tạp. ]

PS: Mình mới sử dụng android nên không biết có phải bản hack hay không, mong các bạn tìm bản hack hay hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.