4

我已经成功创建了一个云端点模型,可以轻松地从 App Engine 检索信息。为了减少往返并提供更快的用户体验,我确定了一个我希望存储到本地存储的实例。

在我的应用程序的其余部分,我使用 ObjectInputStream 来读取和写入对象,例如:

FileInputStream fis = context.openFileInput("PRIVFILE");
ObjectInputStream ois = new ObjectInputStream(fis);
AppModelState s = (AppModelState) ois.readObject();

这显然需要所有数据成员实现 Serializable 接口。Model 类扩展了 GenericJSON 并且不是“Serializable”,因为

    public final class ModelClass extends GenericJson {}

我可以手动创建一个映射到模型的可序列化对象;但是,由于属性的数量,这似乎很业余。

我考虑的另一种选择是创建一个可序列化的对象包装器,它只是将 JSON 字符串作为成员,并提供一个接受 ModelClass 作为参数的 setter/getter,例如:

class AppModelState implements Serializable {
   private String modelClassJSON;

   public ModelClass getModelClass() {
      // generate a new ModelClass from the JSON
   }

   public void setModelClass(ModelClass c) {
      // extract the JSON for storage
   }

   .....
}

我觉得必须有更好的方法,这应该已经解决了十几次,但我没有找到任何资源。请提供输入。

4

2 回答 2

6

我做的和你在问题中所说的完全一样。

由于 Cloud Endpoints 对象已经序列化以通过线路传输,因此它们也可以序列化以存储在本地。作为额外的奖励,使用 Android 3.0 或更高版本,您甚至不需要导入任何库——它已经存在!例如:

import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;

private static final JsonFactory JSON_FACTORY = new AndroidJsonFactory();

public void putObject(String key, Object value) throws Exception {
    byte[] outputbytes = null;
    if (value instanceof GenericJson) {
        outputbytes = JSON_FACTORY.toByteArray(value);
    } else {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        ObjectOutputStream objectstream = new ObjectOutputStream(output);
        objectstream.writeObject(value);
        objectstream.close();
        outputbytes = output.toByteArray();
    }

    // persist "outputbytes" ...
}

public <T> T getObject(String key, Class<T> outclass) throws Exception {
    // retrieve saved bytes...
    byte[] valuebytes = ...

    if (valuebytes[0] == '{' && valuebytes[1] == '"' && valuebytes[valuebytes.length-1] == '}') {
        // Looks like JSON...
        return JSON_FACTORY.fromString(new String(valuebytes, "UTF-8"), outclass);
    } else {
        ByteArrayInputStream input = new ByteArrayInputStream(valuebytes);
        ObjectInputStream objectstream = new ObjectInputStream(input);
        Object value = objectstream.readObject();
        objectstream.close();
        return outclass.cast(value);
    }
}

请注意,AndroidJsonFactory在序列化长字符串时,默认值(无论如何从 Android v4.3 开始)非常慢。JacksonFactory如果您遇到性能问题,请创建一个新的。其他一切都保持不变。

更新: 如果你想序列化一个 GenericJson 对象列表,你只需要创建一个包含这些对象列表的 GenericJson 对象。例如:

import com.google.api.client.json.GenericJson;
import com.google.api.client.util.Key;

public static class PersistantJson extends GenericJson {
    @Key public int one;
    @Key public String two;
}

public static class PersistantJsonList extends GenericJson {
    @Key public List<PersistantJson> list = new ArrayList<PersistantJson>();
}

您现在可以将所有PersistantJson(即“生成云端点客户端库”创建的某个类)对象添加到变量的.list元素,PersistantJsonList然后将该变量传递给putObject(). 请注意,这要求列表中的所有对象都属于同一类,以便反序列化知道类型是什么(因为 JSON 序列化不记录类型)。如果您使用List<Object>,那么回读的是 aList<Map<String, Object>>并且您必须手动提取字段。

于 2013-11-24T20:52:01.150 回答
1

我认为对将与 Endpoints 一起使用的类进行标准 Java 序列化效果不佳。问题是序列化是二进制的,HTTP comm 是字符串。

如果您自己进行 HTTP 通信,而不是使用端点,我认为您会遇到同样的问题。为了发送对象,您将对其进行序列化(将字符串成员转换为二进制),然后您必须将二进制转换回字符串。

因此,如果您使用的数据量不是太多,将您的对象存储为 JSON 可能是最简单的。

于 2013-03-11T02:30:04.593 回答