2009-10-28 26 views
21

說我有一個可序列化的Java Bean對象。我想在活動通過onDestroy()的目的(即onSaveInstanceState()是而不是調用)安全地存儲它。如何在Activity重新啓動時保留一個複雜的對象?

我正在尋找一種不涉及創建數據庫並寫入對象的方式(主要是因爲a)Android的數據庫API太糟糕了,而且b)由於數據庫使應用程序更新成爲一場噩夢,因爲沒有像樣的東西支持應用遷移)。

我想過將對象序列化爲ByteArrayOutputStream,base64將其編碼並將其作爲字符串寫入SharedPreferences文件。或者那太遙遠了?

UPDATE

也許這連載到字符串的想法並不壞畢竟,似乎工作得非常好。下面是我現在在做什麼:

public static String objectToString(Serializable object) { 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    try { 
     new ObjectOutputStream(out).writeObject(object); 
     byte[] data = out.toByteArray(); 
     out.close(); 

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

     return new String(out.toByteArray()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

public static Object stringToObject(String encodedObject) { 
    try { 
     return new ObjectInputStream(new Base64InputStream(
       new ByteArrayInputStream(encodedObject.getBytes()))).readObject(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 
中的onDestroy

()然後我可以簡單地寫中的Base64字符串中的首選項文件,其中,直到我的下一個活動期間推出看了一遍它是安全的。它比我預期的要快得多,除非你的豆子傳輸了大量的數據,它運行得非常好。更好的是,您不必維護數據庫模式。

不過,我很好奇別人如何做到這一點。

+0

是沒可能只使用捆綁呢? – JRL 2009-10-28 13:55:54

+0

怎麼樣?如果您的活動通過onSaveInstanceState(),即運行時將其銷燬,則只能訪問該包。 – Matthias 2009-10-28 14:12:27

+0

太棒了!我用你的方法,它的工作原理。唯一的問題是Android SDK中的Base64InputStream沒有一個構造函數,它只有一個參數,現在它有一個額外的int標誌參數。只需將其設置爲0或8,如果您在對象中有任何url信息。 – JPM 2011-05-02 18:29:30

回答

9

我找這不 涉及創建一個數據庫,並編寫 的對象來表示(主要是因爲一) Android的DB API是可怕和b) 因爲數據庫使應用 更新一個辦法噩夢,因爲 沒有體面的支持申請 遷移)。

Android的API實際上是相當合理的,主要是因爲它是SQLite API的一個精簡包裝器,SQLite API對嵌入式數據庫來說是相當合理的。此外,Android通過SQLiteOpenHelper爲應用程序升級的模式升級提供了幫助。

這比我預期的要快了很多, 除非你的豆子進行海量數據的 ,它工作得很好。

我聽說有更多的開發人員從序列化中逃跑尖叫,而我聽說有長期成功的人。就在過去的幾天裏,在SO #android的這裏,我和一個人拼命交流,試圖從根源上撕掉他的應用程序中的序列化。

甚至更​​好的是,您不必維護數據庫模式。

哦,是的,你做的。當您更新您的應用程序並且您的課程被修改時,您認爲會發生什麼?做bookkeeping來弄清楚如何從新版本的類反序列化舊版本的類是一件苦差事,是開發人員放棄序列化的原因之一。另外,不要忘記序列化不是事務性的,而SQLite是。

+1

對不起,我完全不同意。不得不維護一個數據庫來暫時存儲一個簡單的對象,這對我來說似乎不僅僅是一點點過分。另外,我知道SQLiteOpenHelper及其所有限制,而且我發現DB遷移是後面的一個主要難題。 另外,這裏不需要維護,因爲我可以在存儲對象之前清除()編輯器,而不管它的結構如何。認爲基於文檔的數據庫,沒有模式。對於數據庫,只要模型發生變化,我就必須刪除表。 – Matthias 2009-10-28 14:16:15

+5

各自爲戰。 – CommonsWare 2009-10-28 20:06:59

+0

如果你正在保存一個複雜的對象,並且不想經歷定義對象上每個數據點的所有列的麻煩,Matthias方法很好用。 – JPM 2011-05-02 18:31:34

3

我還在尋找un/marshalling任何bean或活動狀態的好方法。我們都知道Activity的onStoreInstanceState()和onRestoreInstanceState()是多麼的痛苦。

我的活動只是將它們的狀態存儲在onPause()中,並通過直接對象序列化將它們恢復到onCreate()生命週期鉤子中。

像你這樣通過字符串進行序列化當然是可能的,但不太適合大數據並導致大量開銷。此外,首選項實際上用於存儲首選項,而不是數據:)不幸的是,Parcelable/Parcel可用於此目的,不建議存儲到持久性存儲。

那麼是什麼遺留下來的是一個簡單的對象序列化 - 幸好Android SDK有執行的ObjectInputStream和ObjectOutputStream的班級,所有的缺點和優點的 - 就像我們也將做一個非Android Java世界中,一個簡單的:

ObjectOutputStream.writeObject(yourPojo) 

會做魔術對我們來說,(記得要實現Serializable標記接口)

此外,您可能希望在以下上下文中的API來查找 - ContextWrapper - 活動,這是緩存當地非常有用數據(如圖像)等:

.getCacheDir() 
.getDir() 
.openFileInput() 
.openFileOutput() 

快樂的黑客:)

相關問題