6

Sau khi trải qua một cuốn sách lập trình Android giới thiệu, tôi muốn thay đổi ứng dụng ví dụ để củng cố sự hiểu biết của tôi về một số chủ đề không thực sự được đề cập đến. Trong khi thực hiện thay đổi, tôi đã mắc lỗi, nhưng tôi tò mò vì sao lỗi này hoạt động trong một số trường hợp nhưng không phải trong các trường hợp khác.Tại sao lưu một Hashtable của các đối tượng không phải Parcelable trong onSaveInstanceState() đôi khi làm việc?

Một hoạt động trong ứng dụng lưu trữ một loạt các câu hỏi trong một số Hashtable<Integer, Question>, trong đó Câu hỏi là một lớp nhỏ chứa một chuỗi int và hai. Như được viết ban đầu, hoạt động tải các câu hỏi từ một máy chủ trên mỗi onCreate(), vì vậy tôi muốn triển khai onSaveInstanceState() để ngăn một số tải xuống thừa. onSaveInstanceState() lưu Hashtable vào Gói bằng cách sử dụng putSerializable().

@Override 
protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
      // mQuestions is a member variable of 
      // type Hashtable<Integer, Question> 
    if (mQuestions != null && mQuestions.size() > 0) { 
     outState.putSerializable(SAVED_QUESTIONS, mQuestions); 
    } 
} 

Nó hoạt động hoàn hảo cho những thay đổi định hướng màn hình ngay cả trước khi tôi biết Parcelable là gì hoặc cách triển khai. Tôi chỉ biết có một vấn đề khi tôi nhấn phím home giả lập và ứng dụng âm thầm, vô tình bị rơi mà không có đầu ra LogCat. Việc theo dõi ngăn xếp dẫn tôi để tìm kiếm Parcelable và làm cho câu hỏi thực hiện nó.

Câu hỏi của tôi không phải là những gì tôi đã làm sai. Câu hỏi đặt ra là: Khi lớp Question không thực hiện Parcelable, tại sao ứng dụng chỉ gặp sự cố khi nhấn Home và không thay đổi hướng màn hình?

+0

"onSaveInstanceState() lưu hàm băm vào gói bằng cách sử dụng putSerializable()." - không đặt mô hình dữ liệu của bạn trong trạng thái ví dụ. Đặt mô hình dữ liệu của bạn vào một tệp hoặc một cơ sở dữ liệu. Đó là cách bạn "ngăn chặn tải xuống dư thừa". "Chỉ biết có một vấn đề khi tôi nhấn phím home giả lập và ứng dụng âm thầm, vô tình bị rơi mà không có đầu ra LogCat." - và bằng chứng của vụ tai nạn vô hình, im lặng này ... là gì, chính xác? – CommonsWare

+0

@CommonsWare: Một cửa sổ popup xuất hiện trong Eclipse yêu cầu mở phối cảnh Debug vì khởi chạy đã bị treo. Đó là cách tôi biết nó bị rơi. Tôi đã nhận xét ra các mã để làm cho câu hỏi Parcelable, và trên một thử (trong số nhiều), nó đã buộc chặt chẽ với các lỗi đăng nhập, nhưng điều đó đã không xảy ra trước khi gửi câu hỏi này. – erichamion

+0

Có, dữ liệu thực sự cần được lưu vào một tệp, nhưng đó không phải là những gì tôi đang cố gắng làm. Tôi không làm việc tại một ứng dụng sản xuất (ngay cả đối với cá nhân, sở thích sử dụng). Tôi đã sửa đổi ứng dụng demo được tạo ra thông qua cuốn sách Phát triển ứng dụng Android của chính mình trong cuốn sách 24 Hours_. Ngay cả đối với một cuốn sách giới thiệu, nó dường như để lại một số chủ đề rất cơ bản. Tôi muốn xem cách onSaveInstanceState() hoạt động. Tôi nghĩ rằng tôi có cơ chế của nó xuống ngay bây giờ, nếu không phải khi nào và làm thế nào tốt nhất để sử dụng nó. – erichamion

Trả lời

1

Trích dẫn Steve Moseley

Lưu ý rằng nó là KHÔNG an toàn để sử dụng onSaveInstanceStateonRestoreInstanceState, theo các tài liệu về trạng thái hoạt động trong http://developer.android.com/reference/android/app/Activity.html.

Các trạng thái tài liệu (trong phần 'Hoạt động Vòng đời'):

Lưu ý rằng điều quan trọng là tiết kiệm dữ liệu liên tục trong onPause() thay của onSaveInstanceState(Bundle) vì sau này không phải là một phần của vòng đời callbacks, do đó, sẽ không được gọi trong mọi tình huống như được mô tả trong tài liệu của nó.

Nói cách khác, đặt mã lưu/khôi phục của bạn trong onPause()onResume() thay thế!

+0

Điều này sẽ thích hợp hơn làm nhận xét về câu hỏi gốc, vì nó không phải là câu trả lời cho câu hỏi như được đăng: "... tại sao ứng dụng chỉ gặp sự cố khi nhấn Home chứ không phải thay đổi hướng màn hình?" – glorifiedHacker

2

Theo tôi hiểu Android không tuần tự hóa trạng thái mẫu khi tạo lại hoạt động sau khi thay đổi cấu hình. Đó là lý do tại sao mã của bạn hoạt động. Các đối tượng liên tục không cần phải có thể chuyển nhượng được vì chúng chỉ tồn tại trong bộ nhớ.

Điều này trông giống như tối ưu hóa. Android biết rằng quá trình sẽ không bị chấm dứt trong trường hợp này và không cần phải lưu trạng thái cá thể vào một tệp. (Về lý thuyết quá trình có thể được chấm dứt trong quá trình thay đổi cấu hình và tôi không thực sự biết cách Android giải quyết vấn đề này).

Nhưng khi người dùng nhấn phím Home, ứng dụng của bạn sẽ trở thành nền. Và quá trình của nó có thể được chấm dứt trong trường hợp bộ nhớ thấp. Android cần lưu trạng thái của hoạt động vào một tệp để có thể khôi phục ứng dụng của bạn và các hoạt động của ứng dụng trong tương lai. Trong trường hợp này, trạng thái cá thể thực sự được tuần tự hóa và được lưu vào lưu trữ liên tục.Và đó là lý do tại sao mã của bạn không hoạt động.

Quá trình chấm dứt có thể xảy ra bất kỳ lúc nào, do đó bạn không thể dựa vào một số chi tiết triển khai. Chỉ cần làm cho trường hợp thể hiện có thể được chuyển nhượng hoặc có thể tuần tự hóa và bạn sẽ không phải đối mặt với vấn đề này một lần nữa.

+0

Mặc dù tôi chưa tự xác nhận, câu trả lời này có ý nghĩa đối với tôi (tại sao lại sắp xếp thứ gì đó để thay đổi cấu hình khi các biến vẫn tồn tại trong bộ nhớ). Nó cũng là câu trả lời duy nhất cho đến nay mà cố gắng để giải quyết các câu hỏi ban đầu như được đăng bởi erichamion. Vì vậy tôi đang trao phần thưởng cho câu trả lời này. – glorifiedHacker

0

Ứng dụng không gặp sự cố. Nó chỉ đơn giản là tắt khi người dùng nhấp vào phím Home. Đó là lý do tại sao không có đầu ra cho LogCat.

Đặt điểm ngắt trong Activity.onDestroy() để xác nhận điều này. Nếu tôi đúng onDestroy() sẽ được gọi nhưng onSaveInstanceState() sẽ không, bởi vì onSaveInstanceState() chỉ được gọi khi ứng dụng được đặt ở trạng thái nền, không phải khi nó được tắt.

Nếu bạn cần lưu trạng thái ứng dụng khi tắt máy, hãy đặt mã trong onDestroy() và lưu mã vào thứ gì đó dai dẳng hơn Gói.

Barry

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