2013-03-07 52 views
4

我已經成功創建了一個雲端點模型,可以輕鬆從App Engine中檢索信息。爲了減少往返並提供更快的用戶體驗,我確定了一個我希望存儲到本地存儲的實例。將雲端點模型類序列化爲Android文件系統的方法

在我的應用程序的其餘部分,我使用ObjectInputStream的讀取和寫入的對象,如:

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

這顯然需要的所有數據成員實現Serializable接口。 Model類擴展了GenericJSON並且不是「Serializable」,因爲我可以手動創建映射到模型的可序列化對象;然而,由於屬性的數量,這似乎非常業餘。

另一種選擇我認爲是創建簡單地具有JSON字符串作爲成員,並提供設置器/吸氣劑接受ModelClass作爲參數,例如序列化的對象的包裝:

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 
    } 

    ..... 
} 

我覺得好像有必須是一個更好的方法,這應該已經解決了十幾次,但我沒有找到任何資源。請提供意見。

回答

1

我認爲做與終端一起使用的類的標準Java序列化不能很好地工作。問題是序列化是二進制的,並且HTTP comm是字符串。

如果你自己在做HTTP通訊,而不是使用端點,我想你會遇到同樣的問題。爲了發送對象序列化(將字符串成員轉換爲二進制文件),然後你必須將二進制文件轉換回字符串。

因此,如果您使用的數據量不是太多,那麼將對象存儲爲JSON可能最容易。

5

我和你在你的問題中說的完全一樣。

由於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 4.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(即通過一些「生成雲終端客戶端庫」創建的類)對象的PersistantJsonList變量的.list元素,然後將該變量傳遞給putObject()。請注意,這要求列表中的所有對象具有相同的類,以便反序列化知道類型是什麼(因爲JSON序列化不會記錄類型)。如果您使用List<Object>,則回讀內容爲List<Map<String, Object>>,您必須手動提取這些字段。

+0

@Brain你知道一種反序列化雲端點對象的**列表**的方法嗎? – AsafK 2013-12-08 00:10:12

+0

@AsafK,這是一個很好的問題。我並沒有試圖這樣做,只好玩了一下才得以實現。我用我發現的內容更新了我的答案。如果你的雲端點庫包含一個其他對象列表的對象,那麼我認爲它已經「只是工作」(儘管我沒有嘗試過)。 – 2013-12-09 02:48:25

-1

這似乎是一個公開的問題。

最終的關鍵字阻止我們擴展類並使其可串行化,以便我們可以在活動之間交換由Cloud EndPoints返回的對象。因此,建議的子分類解決方案在這種情況下無法工作。

有人知道另一種解決方案嗎?

+0

這應該是一個評論而不是答案。 – 2015-09-19 08:50:53

相關問題