2009-10-28 24 views
21

Giả sử tôi có một đối tượng Java Bean có thể tuần tự hóa. Tôi muốn lưu trữ nó một cách an toàn khi Hoạt động đi qua onDestroy() với mục đích (ví dụ: onSaveInstanceState() là không phải là được gọi).Làm cách nào để giữ lại một đối tượng phức tạp trong Hoạt động khởi động lại?

Tôi đang tìm một cách không liên quan đến việc tạo cơ sở dữ liệu và viết đối tượng đó (chủ yếu là do a) API DB của Android là khủng khiếp và b) vì cơ sở dữ liệu cập nhật ứng dụng một cơn ác mộng, vì không có hỗ trợ cho việc áp dụng di chuyển).

Tôi đã nghĩ về việc sắp xếp từng đối tượng thành một ByteArrayOutputStream, mã hóa base64 và ghi nó vào một tệp SharedPreferences dưới dạng một chuỗi. Hay là quá xa?

CẬP NHẬT

Có lẽ đó là ý tưởng serialize-to-string là không phải là xấu sau khi tất cả, dường như làm việc ra khá tốt. Đây là những gì tôi đang làm bây giờ:

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

trong onDestroy() Tôi có thể sau đó chỉ cần viết chuỗi Base64 vào một tập tin sở thích, nơi đó là an toàn cho đến khi tôi đọc nó một lần nữa trong sự ra mắt hoạt động tiếp theo. Đó là nhanh hơn rất nhiều so với tôi mong đợi và trừ khi đậu của bạn mang theo một lượng lớn dữ liệu, nó hoạt động khá tốt. Và thậm chí tốt hơn, bạn không phải duy trì một lược đồ DB.

Tuy nhiên, tôi rất tò mò về cách người khác làm điều này.

+0

Bạn không thể chỉ sử dụng Gói thay thế? – JRL

+0

như thế nào? bạn chỉ có thể truy cập gói nếu hoạt động của bạn đi qua onSaveInstanceState(), tức là khi hoạt động đó bị thời gian chạy hủy. – Matthias

+0

Tuyệt vời! Tôi đã sử dụng cách tiếp cận của bạn và nó hoạt động. Chỉ có vấn đề tôi đã có là Base64InputStream trong Android SDK không có một hàm tạo có một tham số bây giờ nó có một tham số cờ int bổ sung. Chỉ cần đặt giá trị đó thành 0 hoặc 8 nếu bạn có bất kỳ thông tin url nào trong Đối tượng. – JPM

Trả lời

9

Tôi đang tìm kiếm một cách mà không làm liên quan đến việc tạo ra một cơ sở dữ liệu và viết đối tượng đó (chủ yếu là từ a) DB API Android là khủng khiếp và b) từ cơ sở dữ liệu làm cho ứng dụng cập nhật một cơn ác mộng, bởi vì có không có hỗ trợ phong nha cho việc áp dụng di chuyển ).

API của Android thực sự khá hợp lý, chủ yếu là vì nó là một trình bao bọc mỏng hơn API SQLite và API SQLite khá hợp lý cho cơ sở dữ liệu được nhúng. Hơn nữa, Android cung cấp hỗ trợ cho việc nâng cấp giản đồ về nâng cấp ứng dụng, thông qua SQLiteOpenHelper.

Nhanh hơn rất nhiều so với dự kiến ​​của tôi và trừ khi đậu của bạn mang số tiền khổng lồ dữ liệu, nó hoạt động khá tốt.

Tôi đã nghe nói về nhiều nhà phát triển khác đang chạy trốn khỏi việc tuần tự hóa hơn là tôi đã nghe nói về những người có thành công lâu dài với nó. Chỉ trong vài ngày qua, ở đây trên SO #android, tôi đã có một cuộc trao đổi với ai đó cố gắng tuyệt vọng để rip serialization ra khỏi ứng dụng của mình bằng rễ.

Và thậm chí tốt hơn, bạn không phải duy trì giản đồ DB.

Ồ đúng vậy. Bạn nghĩ điều gì sẽ xảy ra khi bạn cập nhật ứng dụng của bạn và lớp học của bạn được sửa đổi? Làm bookkeeping để tìm ra cách để deserialize phiên bản cũ của lớp học từ một phiên bản mới của một lớp học là một việc vặt và là một trong những lý do các nhà phát triển từ bỏ serialization.Ngoài ra, đừng quên rằng tuần tự hóa không phải là giao dịch, trong khi SQLite là.

+1

Xin lỗi, tôi hoàn toàn không đồng ý. Việc phải duy trì một cơ sở dữ liệu để lưu trữ một đối tượng đơn giản tạm thời có vẻ nhiều hơn một chút so với tôi. Thêm vào đó, tôi biết về SQLiteOpenHelper và tất cả những hạn chế của nó, và tôi thấy sự di cư của DB là một nỗi đau lớn ở phía sau. Ngoài ra, KHÔNG yêu cầu bảo trì ở đây, vì tôi chỉ có thể xóa() trình chỉnh sửa trước khi lưu trữ một đối tượng, bất kể cấu trúc của nó là gì. Hãy nghĩ về cơ sở dữ liệu dựa trên tài liệu, không có lược đồ. Với một DB, tôi sẽ phải DROP TABLE bất cứ khi nào mô hình thay đổi. – Matthias

+5

Đối với mỗi của riêng mình. – CommonsWare

+0

Phương pháp Matthias hoạt động tuyệt vời nếu bạn đang lưu một đối tượng phức tạp và không muốn trải qua những rắc rối khi xác định tất cả các cột cho mỗi datapoint trên một đối tượng. – JPM

3

Tôi cũng đang tìm kiếm một cách tiếp cận tốt đẹp để bỏ/marshalling bất kỳ đậu hoặc trạng thái hoạt động nào. Chúng ta đều biết có bao nhiêu Activity onStoreInstanceState() và onRestoreInstanceState() là một cơn đau.

Hiệu ứng của tôi chỉ đơn giản là lưu trữ trạng thái của chúng trong onPause() và khôi phục chúng trong móc nối vòng đời onCreate() thông qua serialization đối tượng trực tiếp.

Nối tiếp qua chuỗi như bạn làm, tất nhiên là có thể nhưng ít phù hợp hơn với dữ liệu lớn và gây ra rất nhiều chi phí. Hơn nữa Preferences thực sự ở đó để lưu trữ các sở thích, không phải dữ liệu :) Thật không may, các Parcelable/Parcel những gì chúng ta có thể sử dụng cho mục đích này, không khuyên bạn nên lưu trữ để lưu trữ liên tục.

Vì vậy, những gì còn lại là một serialization đối tượng đơn giản - may mắn thay android SDK có thực hiện các lớp ObjectInputStream và ObjectOutputStream với tất cả các nhược điểm và lợi ích - như chúng tôi cũng sẽ làm trong một thế giới Java phi android, một đơn giản:

ObjectOutputStream.writeObject(yourPojo) 

sẽ làm điều kỳ diệu cho chúng ta, (nhớ để thực hiện các marker giao diện Serializable)

Ngoài ra, bạn có thể muốn nhìn vào API của một bối cảnh sau - ContextWrapper - Hoạt động, rất hữu ích cho bộ nhớ cache cục bộ dữ liệu (chẳng hạn như hình ảnh), v.v.

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

hack hạnh phúc :)

Các vấn đề liên quan