以共享首选项存储和检索类对象


111

在Android中,我们可以以共享的首选项存储类的对象并在以后检索该对象吗?

如果有可能怎么办呢?如果不可能的话,还有其他的可能性吗?

我知道序列化是一种选择,但是我正在寻找使用共享首选项的可能性。


我添加了一个帮助程序库,以防有人需要它:github.com/ionull/objectify
Tsung Goh


这是类似问题的答案
tpk


您可以使用这个内置很多功能的库。github.com/moinkhan-in/PreferenceSpider
Moinkhan '18

Answers:


15

不可能。

您只能在SharedPrefences SharePreferences.Editor中存储简单值

您需要保存的课程特别是什么?


1
谢谢。我想存储该类的一些数据成员。我不想使用共享首选项存储数据成员的每个值。我想将其存储为一个对象。如果没有共享首选项,我还有其他选择吗?
androidGuy 2011年

5
序列化并将其存储在数据库(SQLite)/平面文件中。
布隆德尔

5
答案不完整。可能的解决方案是将pojo转换为ByteArrayOutPutStream并另存为String到SharedPreferences中
rallat 2012年

27
另一个选项将其另存为json,然后将其重新映射。使用GSON或jackSON真的很容易
rallat 2012年

2
让我把时间机器恢复到2011年并弄清楚
-Blundell

324

是的,我们可以使用Gson做到这一点

GitHub下载工作代码

SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);

为了保存

Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(myObject); // myObject - instance of MyObject
prefsEditor.putString("MyObject", json);
prefsEditor.commit();

为了得到

Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);

更新1

可以从github.com/google/gson下载最新版本的GSON

更新2

如果您使用的是Gradle / Android Studio,则只需在build.gradle依赖项部分中添加以下内容-

implementation 'com.google.code.gson:gson:2.6.2'

在我的情况下不起作用。即使将jar放入libs并设置了构建路径,Gson类也无法解决。
Shirish Herwade,

清理项目,然后尝试@ShirishHerwade
Parag Chauhan

@parag也不起作用。您能告诉我使用该罐子消除上述错误的步骤吗?因为我成功地将该jar添加到libs文件夹中,然后在“ java build path”中也尝试在桌面上添加外部存储的json
Shirish Herwade,

7
如果它也提到了局限性,那么答案会更好。我们可以并且不能以这种方式存储和检索什么样的对象?显然,它不适用于所有课程。
wvdz 2014年

3
String json = gson.toJson("MyObject");应该是不是String的对象。
艾哈迈德·赫加兹

44

我们可以使用Outputstream将对象输出到内部存储器。并转换为字符串,然后优先保存。例如:

    mPrefs = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor ed = mPrefs.edit();
    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();

    ObjectOutputStream objectOutput;
    try {
        objectOutput = new ObjectOutputStream(arrayOutputStream);
        objectOutput.writeObject(object);
        byte[] data = arrayOutputStream.toByteArray();
        objectOutput.close();
        arrayOutputStream.close();

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Base64OutputStream b64 = new Base64OutputStream(out, Base64.DEFAULT);
        b64.write(data);
        b64.close();
        out.close();

        ed.putString(key, new String(out.toByteArray()));

        ed.commit();
    } catch (IOException e) {
        e.printStackTrace();
    }

当我们需要从首选项中提取对象时。使用如下代码

    byte[] bytes = mPrefs.getString(indexName, "{}").getBytes();
    if (bytes.length == 0) {
        return null;
    }
    ByteArrayInputStream byteArray = new ByteArrayInputStream(bytes);
    Base64InputStream base64InputStream = new Base64InputStream(byteArray, Base64.DEFAULT);
    ObjectInputStream in;
    in = new ObjectInputStream(base64InputStream);
    MyObject myObject = (MyObject) in.readObject();

嗨,我知道这是一段时间前发布的,但是您确定用于提取存储对象的代码正确吗?我在最后两行收到多个错误,抱怨如何需要定义显式构造函数,而不是仅仅具有“ new ObjectInputStream(byteArray)”。谢谢您的帮助!
Wakka Wakka Wakka

嗨,我突然在= new ObjectInputStream(base64InputStream);上收到EOFException。我正在以与您完全相同的方式将其写入共享的首选项。您认为可能有什么问题?
marienke 2013年

将Object编写为pref时,是否有任何异常?从SDK:当程序在输入操作过程中遇到文件或流的末尾时,引发EOFException。
Kislingk 2013年

荣誉,到目前为止,这是我遇到的最佳解决方案。没有依赖关系。但是,应注意,为了能够将ObjectOutput / InputStream用于对象,所述对象和其中的所有自定义对象必须实现Serializable接口。
user1112789 2015年

8

我遇到了同样的问题,这是我的解决方案:

我有要保存到“共享首选项”的类MyClass和ArrayList <MyClass>。首先,我向MyClass添加了一个将其转换为JSON对象的方法:

public JSONObject getJSONObject() {
    JSONObject obj = new JSONObject();
    try {
        obj.put("id", this.id);
        obj.put("name", this.name);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return obj;
}

然后是保存对象“ ArrayList <MyClass> items”的方法:

SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);
    SharedPreferences.Editor editor = mPrefs.edit();

    Set<String> set= new HashSet<String>();
    for (int i = 0; i < items.size(); i++) {
        set.add(items.get(i).getJSONObject().toString());
    }

    editor.putStringSet("some_name", set);
    editor.commit();

这是检索对象的方法:

public static ArrayList<MyClass> loadFromStorage() {
    SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);

    ArrayList<MyClass> items = new ArrayList<MyClass>();

    Set<String> set = mPrefs.getStringSet("some_name", null);
    if (set != null) {
        for (String s : set) {
            try {
                JSONObject jsonObject = new JSONObject(s);
                Long id = jsonObject.getLong("id"));
                String name = jsonObject.getString("name");
                MyClass myclass = new MyClass(id, name);

                items.add(myclass);

            } catch (JSONException e) {
                e.printStackTrace();
         }
    }
    return items;
}

请注意,自API 11起,“共享首选项”中的StringSet可用。


解决了我的问题。我要添加一些东西。首次使用时,我们必须检查集合是否为null。if(set!= null){for(String s:set){..}}
xevser

@xevser我已经按照建议添加了空检查。谢谢。
Micer

6

使用Gson库:

dependencies {
compile 'com.google.code.gson:gson:2.8.2'
}

商店:

Gson gson = new Gson();
//Your json response object value store in json object
JSONObject jsonObject = response.getJSONObject();
//Convert json object to string
String json = gson.toJson(jsonObject);
//Store in the sharedpreference
getPrefs().setUserJson(json);

检索:

String json = getPrefs().getUserJson();

包裹不是通用的序列化机制。此类(以及用于将任意对象放入Parcel的相应的Parcelable API)被设计为高性能IPC传输。因此,将任何Parcel数据放置到持久性存储中是不合适的:在Parcel中任何数据的基础实现中的更改都可能导致较旧的数据不可读。
Marcos Vasconcelos



0

您可以使用“ 复杂首选项Android-Felipe Silvestre”库来存储您的自定义对象。基本上,它使用GSON机制存储对象。

要将对象保存到首选项:

User user = new User();
user.setName("Felipe");
user.setAge(22); 
user.setActive(true); 

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(
     this, "mypref", MODE_PRIVATE);
complexPreferences.putObject("user", user);
complexPreferences.commit();

并取回它:

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(this, "mypref", MODE_PRIVATE);
User user = complexPreferences.getObject("user", User.class);

包裹不是通用的序列化机制。此类(以及用于将任意对象放入Parcel的相应的Parcelable API)被设计为高性能IPC传输。因此,将任何Parcel数据放置到持久性存储中是不合适的:在Parcel中任何数据的基础实现中的更改都可能导致较旧的数据不可读。
Marcos Vasconcelos

不推荐使用
IgorGanapolsky

0

您可以使用Gradle Build.gradle来使用GSON:

implementation 'com.google.code.gson:gson:2.8.0'

然后在您的代码中,例如使用Kotlin对字符串/布尔对:

        val nestedData = HashMap<String,Boolean>()
        for (i in 0..29) {
            nestedData.put(i.toString(), true)
        }
        val gson = Gson()
        val jsonFromMap = gson.toJson(nestedData)

添加到SharedPrefs:

        val sharedPrefEditor = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE).edit()
        sharedPrefEditor.putString("sig_types", jsonFromMap)
        sharedPrefEditor.apply()

现在要检索数据:

val gson = Gson()
val sharedPref: SharedPreferences = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE)
val json = sharedPref.getString("sig_types", "false")
val type = object : TypeToken<Map<String, Boolean>>() {}.type
val map = gson.fromJson(json, type) as LinkedTreeMap<String,Boolean>
for (key in map.keys) {
     Log.i("myvalues", key.toString() + map.get(key).toString())
}

包裹不是通用的序列化机制。此类(以及用于将任意对象放入Parcel的相应的Parcelable API)被设计为高性能IPC传输。因此,将任何Parcel数据放置到持久性存储中是不合适的:在Parcel中任何数据的基础实现中的更改都可能导致较旧的数据不可读。
Marcos Vasconcelos

0

通用共享首选项(CURD)SharedPreference:使用简单的Kotlin类以值键对的形式存储数据。

var sp = SharedPreference(this);

储存资料:

为了存储String,Int和Boolean数据,我们提供了三个名称相同且参数不同的方法(方法重载)。

save("key-name1","string value")
save("key-name2",int value)
save("key-name3",boolean)

检索数据:要检索存储在SharedPreferences中的数据,请使用以下方法。

sp.getValueString("user_name")
sp.getValueInt("user_id")
sp.getValueBoolean("user_session",true)

清除所有数据:要清除整个SharedPreferences,请使用以下代码。

 sp.clearSharedPreference()

删除特定数据:

sp.removeValue("user_name")

共同的共享优先级

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

class SharedPreference(private val context: Context) {
    private val PREFS_NAME = "coredata"
    private val sharedPref: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
    //********************************************************************************************** save all
    //To Store String data
    fun save(KEY_NAME: String, text: String) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putString(KEY_NAME, text)
        editor.apply()
    }
    //..............................................................................................
    //To Store Int data
    fun save(KEY_NAME: String, value: Int) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putInt(KEY_NAME, value)
        editor.apply()
    }
    //..............................................................................................
    //To Store Boolean data
    fun save(KEY_NAME: String, status: Boolean) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putBoolean(KEY_NAME, status)
        editor.apply()
    }
    //********************************************************************************************** retrieve selected
    //To Retrieve String
    fun getValueString(KEY_NAME: String): String? {

        return sharedPref.getString(KEY_NAME, "")
    }
    //..............................................................................................
    //To Retrieve Int
    fun getValueInt(KEY_NAME: String): Int {

        return sharedPref.getInt(KEY_NAME, 0)
    }
    //..............................................................................................
    // To Retrieve Boolean
    fun getValueBoolean(KEY_NAME: String, defaultValue: Boolean): Boolean {

        return sharedPref.getBoolean(KEY_NAME, defaultValue)
    }
    //********************************************************************************************** delete all
    // To clear all data
    fun clearSharedPreference() {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.clear()
        editor.apply()
    }
    //********************************************************************************************** delete selected
    // To remove a specific data
    fun removeValue(KEY_NAME: String) {
        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.remove(KEY_NAME)
        editor.apply()
    }
}

博客:https//androidkeynotes.blogspot.com/2020/02/shared-preference.html


-2

无法将对象存储在SharedPreferences中,我要做的是创建一个公共类,放入所需的所有参数,并创建setter和getter,我能够访问我的对象,


-3

即使在应用程序关闭Donw之后还是刚运行时,您是否仍需要检索该对象?

您可以将其存储到数据库中。
或简单地创建一个自定义Application类。

public class MyApplication extends Application {

    private static Object mMyObject;
    // static getter & setter
    ...
}

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ... android:name=".MyApplication">
        <activity ... />
        ...
    </application>
    ...
</manifest>

然后从每个活动中进行:

((MyApplication) getApplication).getMyObject();

并不是最好的方法,但是它确实有效。


-6

是的。您可以使用Sharedpreference来存储和检索对象

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.