Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/211.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android-具有可序列化对象的SharedReferences_Android_Serialization_Sharedpreferences - Fatal编程技术网

Android-具有可序列化对象的SharedReferences

Android-具有可序列化对象的SharedReferences,android,serialization,sharedpreferences,Android,Serialization,Sharedpreferences,我知道SharedReferences有putString(),putFloat(),putLong(),putInt()和putBoolean()。但是我需要在SharedReferences中存储类型为Serializable的对象。我怎样才能做到这一点呢?简而言之,你不能尝试将你的对象序列化到一个私有文件中,这是同样的事情。样本类别如下: import java.io.FileInputStream; import java.io.FileNotFoundException; import

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

简而言之,你不能尝试将你的对象序列化到一个私有文件中,这是同样的事情。样本类别如下:

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

}

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

无需文件即可完成。

我正在将信息序列化到base64,这样我就可以在首选项中将其保存为字符串

以下代码正在将可序列化对象序列化为base64字符串,反之亦然: 导入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;
    }

}

接受的答案是误导性的,我们可以使用GSON将可序列化对象存储到SharedReference中。阅读更多关于它的信息

您可以在Gradle文件中添加GSON依赖项,方法是:

compile 'com.google.code.gson:gson:2.7'
下面是代码片段:

首先,创建您常用的SharedReference:

//Creating a shared preference
SharedPreferences  mPrefs = getPreferences(MODE_PRIVATE);
从可序列化对象保存到首选项:

 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);
从首选项获取可序列化对象:

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

我们可以使用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)
}
@Throws(jsoniexception::class)
fun Serializable.toJson():字符串{
返回Gson().toJson(this)
}
@抛出(JsonSyntaxException::类)
fun String.to(type:Class):T其中T:Serializable{
返回Gson().fromJson(此类型)
}
@抛出(异常::类)
fun SharedPreferences.Editor.putSerializable(key:String,o:Serializable?)=apply{
putString(key,o?.toJson())
}
@抛出(JsonSyntaxException::类)
有趣的SharedReferences.getSerializable(键:String,类型:Class):T?其中T:Serializable{
返回getString(键,null)?.to(类型)
}
然后使用类似的
get/put()

这里有完整的要点


其他回答中提到的,当数据类结构发生变化时,可能需要考虑迁移。或者至少必须更改用于存储的密钥。

2020:如果要保存对象,最好使用原始数据存储而不是共享引用。

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

  • 用于存储和读取数据(流)的异步API
  • 输入开箱即用安全(协议缓冲区)
  • 可以从UI线程安全调用(下面是Dispatchers.IO)
还有许多其他的好处,比如保证一致性的事务API


查看我的博客文章,了解

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


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

您的代码中的
filename
应该是一个绝对路径(例如:“/data/com.example.myapp/foobar.dat”),还是应该是相对路径(例如:“foobar.dat”)?如API文档中所述,仅仅是一个文件名,不允许使用路径分隔符,int)如何删除您上面的方法保存的文件?我想应该是context.getFileStreamPath(filename.delete();出于好奇-是否应该在“finally”块中关闭FileInputStream和FileOutputStream,以及ObjectInputStream和ObjectOutputStream?可以将上述类粘贴到POJO类中,您可以轻松实现
public YourPojo getFromPreferences(上下文)
public void saveToPreferences(上下文)
,它使用上述两种方法,以及
首选项管理器.getDefaultSharedReferences(上下文)
使用Json很危险。如果我们更改数据结构,反序列化的数据将不匹配。@Elye存储在SharedReferences中的任何信息都与运行时的更改不同步,就像在任何其他数据库中一样。作为编程人员,您有责任在数据更改时注意并存储数据。某些数据库(如Realm and Room)可能不会向您介绍数据库中的更改,但如果加载了数据,则只有您负责将其放回数据库中。Kotlin是一种方法;)