Android - 带有可序列化对象的SharedPreferences

时间:2011-04-28 09:47:16

标签: android serialization sharedpreferences

我知道SharedPreferences有putString()putFloat()putLong()putInt()putBoolean()。但我需要在Serializable中存储SharedPreferences类型的对象。我怎样才能做到这一点?

7 个答案:

答案 0 :(得分:47)

简而言之,你不能尝试将对象序列化为私有文件,这相当于同样的事情。以下样本类:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import android.app.Activity;
import android.content.Context;

/**
 *
 * Writes/reads an object to/from a private local file
 * 
 *
 */
public class LocalPersistence {


    /**
     * 
     * @param context
     * @param object
     * @param filename
     */
    public static void witeObjectToFile(Context context, Object object, String filename) {

        ObjectOutputStream objectOut = null;
        try {

            FileOutputStream fileOut = context.openFileOutput(filename, Activity.MODE_PRIVATE);
            objectOut = new ObjectOutputStream(fileOut);
            objectOut.writeObject(object);
            fileOut.getFD().sync();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (objectOut != null) {
                try {
                    objectOut.close();
                } catch (IOException e) {
                    // do nowt
                }
            }
        }
    }


    /**
     * 
     * @param context
     * @param filename
     * @return
     */
    public static Object readObjectFromFile(Context context, String filename) {

        ObjectInputStream objectIn = null;
        Object object = null;
        try {

            FileInputStream fileIn = context.getApplicationContext().openFileInput(filename);
            objectIn = new ObjectInputStream(fileIn);
            object = objectIn.readObject();

        } catch (FileNotFoundException e) {
            // Do nothing
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (objectIn != null) {
                try {
                    objectIn.close();
                } catch (IOException e) {
                    // do nowt
                }
            }
        }

        return object;
    }

}

答案 1 :(得分:22)

接受的答案具有误导性,我们可以使用GSON将可序列化对象存储到SharedPreferences中。请在google-gson了解详情。

您可以在Gradle文件中添加GSON依赖项:

//Creating a shared preference
SharedPreferences  mPrefs = getPreferences(MODE_PRIVATE);

这里是片段:

首先,创建常用的sharedPreferences:

 Editor prefsEditor = mPrefs.edit();
 Gson gson = new Gson();
 String json = gson.toJson(YourSerializableObject);
 prefsEditor.putString("SerializableObject", json);
 prefsEditor.commit();

从可序列化对象保存到首选项:

Gson gson = new Gson();
String json = mPrefs.getString("SerializableObject", "");
yourSerializableObject = gson.fromJson(json, YourSerializableObject.class);

从首选项获取可序列化对象:

{{1}}

答案 2 :(得分:19)

如果对象是简单的POJO,您可以将对象转换为JSON字符串,并使用putString()将其保存在共享首选项中。

答案 3 :(得分:15)

可以在没有文件的情况下进行。

我正在将信息序列化为 base64 ,并且像这样我可以将其保存为首选项中的字符串。

以下代码将序列化对象序列化为base64字符串,反之亦然:     import android.util.Base64;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;


public class ObjectSerializerHelper {
    static public String objectToString(Serializable object) {
        String encoded = null;
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(object);
            objectOutputStream.close();
            encoded = new String(Base64.encodeToString(byteArrayOutputStream.toByteArray(),0));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return encoded;
    }

    @SuppressWarnings("unchecked")
    static public Serializable stringToObject(String string){
        byte[] bytes = Base64.decode(string,0);
        Serializable object = null;
        try {
            ObjectInputStream objectInputStream = new ObjectInputStream( new ByteArrayInputStream(bytes) );
            object = (Serializable)objectInputStream.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (ClassCastException e) {
            e.printStackTrace();
        }
        return object;
    }

}

答案 4 :(得分:1)

我们可以使用Kotlin创建易于使用的语法。

@Throws(JsonIOException::class)
fun Serializable.toJson(): String {
   return Gson().toJson(this)
}

@Throws(JsonSyntaxException::class)
 fun <T> String.to(type: Class<T>): T where T : Serializable {
 return Gson().fromJson(this, type)
}

@Throws(JsonIOException::class)
fun SharedPreferences.Editor.putSerializable(key: String, o: Serializable?) = apply {
   putString(key, o?.toJson())
}

@Throws(JsonSyntaxException::class)
   fun <T> SharedPreferences.getSerializable(key: String, type: Class<T>): T? where T : Serializable {
    return getString(key, null)?.to(type)
}

,然后使用类似的SharedPreferences将所有可序列化的内容保存到get/put()

在此处Save Serializables in Shared Preferences with Kotlin and GSON

中填写要点

如其他答案中所述,当数据类的结构更改时,您可能必须考虑迁移。否则,至少需要更改用于存储的密钥。

答案 5 :(得分:0)

2020:如果要保存对象,则最好使用Proto DataStore代替SharedPreferences。

与“旧的” SharedPreferences相比,它带来了巨大的好处,即:

  • 用于存储和读取数据(流)的异步API
  • 开箱即用的类型安全性(协议缓冲区)
  • 可以安全地从UI线程(位于下面的Dispatchers.IO)进行调用

还有其他许多好处,例如事务性API,可以保证一致性。

查看我的博客文章以查看how to implement Proto DataStore easily

答案 6 :(得分:0)

如果您的对象与嵌套对象很复杂,并且有一天您可能需要删除一个嵌套对象,那么这是一种糟糕的机制,因为您将需要实施自己的迁移策略(除非将所有数据都扔掉没问题)。

如果是大量数据,这种机制缺乏事务支持。那你自己写吗?还是使用更合适的存储机制?我强烈建议使用更合适的存储机制,例如 SQLite DB 的文件系统。