2015-05-27 38 views
15

Trong ứng dụng của tôi, tôi lưu trữ một số dữ liệu quan trọng trong SharedPreferences - nó hoạt động như tôi cần. Bây giờ tôi muốn tạo thông điệp tường trình cho một số tình huống không chính xác.Khi Android SharedPreferences commit() trả về false?

Tôi có thông báo cho trường hợp, khi tùy chọn trống hoặc chỉ ném một số ngoại lệ trong khi tải. Chỉ tình huống không chính xác trong khi lưu có thể xuất hiện nếu phương thức commit() trả về false - Tôi không biết tại sao nó có thể xảy ra và tôi nên làm gì trong trường hợp đó.

Câu hỏi đặt ra là - khi nào phương thức commit() trả về false? Và có thể while(!editor.commit()) {;} là giải pháp để thành công không?

+0

Trả về true nếu các giá trị mới được ghi thành công thành lưu trữ liên tục. Hãy xem: http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#commit() –

+0

và tôi nghĩ rằng nó trả về false khi tệp bị hỏng hoặc bất kỳ sự cố nào với I/O .. nhưng những vấn đề này xảy ra rất hiếm khi ... – Moinkhan

+0

xem xét nếu u thay đổi kiểu dữ liệu cho một khóa tại một số điểm. Nó chắc chắn sẽ trả về false. – Randroid

Trả lời

10

Trước tiên, bạn sẽ không bao giờ muốn làm: while(!editor.commit()) {;}. Nếu bạn muốn thử lại một cam kết, bạn sẽ làm như vậy một số lần thay vì lặp mãi mãi.

Khi cam kết() trả về -1: Cả cam kết() và áp dụng() thực hiện thay đổi đối với bộ nhớ và sau đó thực hiện cuộc gọi để ghi các thay đổi vào đĩa (per source). commit() đợi ghi đĩa quay lại để trả về kết quả. Vì vậy, câu trả lời cho câu hỏi của bạn là: "Khi lưu trạng thái ưu tiên vào đĩa không thành công cho lệnh gọi commit() cụ thể của bạn." Kể từ khi thay đổi được phản ánh trong bộ nhớ họ có thể hoặc có thể không được ghi vào đĩa bởi một cam kết() hoặc áp dụng() gọi trước hoặc sau khi ghi đĩa cố gắng của bạn (nghĩ chủ đề đua). Vì không có mã để khôi phục bản cập nhật bộ nhớ và SharedPreferences là các thành phần khác (per source) khác trong ứng dụng của bạn sẽ thấy các thay đổi của bạn ngay cả khi chúng không lưu vào đĩa.

Tóm lại, lặp lại một vài lần (không phải mãi mãi) để đảm bảo một cam kết() ghi vào đĩa có vẻ tốt để giúp bạn vượt qua một vấn đề I/O intermitten, nhưng nó sẽ là một tình huống I/O hiếm nó thất bại. Nếu bạn cần phạm vi cam kết hoàn hảo, bạn sẽ muốn đọc lại đĩa để xác thực mỗi cam kết() cuộc gọi có tác động hiệu suất và là quá mức cần thiết cho tất cả trừ một tập hợp các tình huống nhỏ.

5

commit() có thể trả về false nếu có vấn đề trong việc lưu dữ liệu của bạn.

Nhìn vào sự khác biệt giữa commit()apply() để có được một ý tưởng rõ ràng hơn (lấy từ this site)

apply()

này giúp tiết kiệm dữ liệu của bạn vào bộ nhớ ngay lập tức và lưu dữ liệu vào đĩa trên một chuỗi riêng biệt. Vì vậy, không có cơ hội chặn chủ đề chính (ứng dụng của bạn sẽ không bị treo).

Đây là kỹ thuật ưu tiên nhưng chỉ có sẵn từ Gingerbread (API 9, Android 2.3).

cam kết()

Calling này sẽ lưu dữ liệu vào file tuy nhiên, quá trình này là thực hiện trong chủ đề đó gọi nó, dừng lại mọi thứ khác cho đến khi tiết kiệm được hoàn tất. Nó trả về đúng khi hoàn tất thành công, sai về lỗi.

Sử dụng commit() nếu bạn cần xác nhận thành công của việc lưu dữ liệu hoặc nếu bạn đang phát triển cho các thiết bị có sẵn Gingerbread. cam kết() đã có sẵn từ API 1

+0

Dòng 'nếu bạn cần xác nhận sự thành công của việc lưu dữ liệu của bạn về tôi, vì vậy tôi không cần thông tin về sự khác biệt. – Ircover

11

Và có thể trong khi (editor.commit()!) {;} là giải pháp cho sự thành công không?

'cam kết' hoạt động là đồng bộ và thực hiện trên thread UI, do đó, nếu bạn có một số lỗi không thể phục hồi mà xảy ra mỗi khi bạn cố gắng để thực hiện commit, bạn sẽ chặn toàn bộ thread UI của bạn với mã này và người sử dụng sẽ thấy ANR. Không tốt. Mặt khác,
'áp dụng' không đồng bộ, do đó, nó không thể chặn chuỗi giao diện người dùng ngay cả khi bạn sẽ thực hiện chuỗi đó vô thời hạn.
Tài liệu nói rất ít về các lỗi có thể xảy ra của hoạt động 'cam kết' (xem ở đây here, herethere). Các tùy chọn được lưu trữ bên trong tệp xml được lưu trữ trên bộ nhớ trong của bạn, do đó, một lỗi có thể có thể là tệp xml bị hỏng. Điều thứ hai có thể được tìm thấy trong documentation:

Lưu ý rằng khi hai biên tập viên đang thay đổi sở thích cùng thời gian, người cuối cùng để gọi cam kết chiến thắng.

Có rất ít việc bạn có thể làm đối với tệp bị hỏng và, đừng cố gắng sửa đổi tùy chọn từ các địa điểm khác nhau cùng một lúc. :)

3

Tôi sẽ tiếp cận vấn đề này từ một góc khác hoàn toàn.

Có một số cách thay thế để giải quyết vấn đề này.

Điều tôi làm là khi chương trình của tôi chạy lần đầu tiên, tôi khởi tạo giá trị ưu tiên được chia sẻ của mình thành giá trị kiểm tra để tôi kiểm tra xem nó có bị thay đổi hay không .

ví dụ:

editor.putInt("key", -1); 

Sau đó, trong hoạt động nơi tôi đang lấy giá trị của sở thích:

int mySavedInt = this.pref.getInt("key", howIgetMyInt) 
if(mySavedInt==-1){ 
    // I know it's not my saved int :) and hasn't been set. 
} 

Hoặc để thực sự sử dụng một sở thích chia sẻ bản thân để xác định xem sở thích chia sẻ bạn đang cố gắng xác thực đã được cập nhật.

ví dụ:

String getStatus = pref.getString("checkMySharedPreferences", "nil"); 
    if (getStatus.equals("true")) { 
     // DO something. 
    } else { 
     Toast.makeText(this, "Set your preferences", 
       Toast.LENGTH_SHORT).show(); 
    } 

Sau đó, khi bạn đặt tùy chọn chia sẻ của bạn, bạn có thể thiết lập giá trị này thành "true":

editor.putString("checkMySharedPreferences", "true"); 
editor.commit(); 

gợi ý khác là để đảm bảo bạn xác nhận bất kỳ dữ liệu trước khi cập nhật sở thích chia sẻ của bạn. Bằng cách đó, các tùy chọn được chia sẻ sẽ không được đặt nếu dữ liệu không hợp lệ.

if(my data is valid){ 
    my shared preferences 
    commit 
} 

Đề xuất cuối cùng là thực hiện kiểm tra tuần hoàn (vì bạn không an toàn trong quá trình) và khi bạn nhận dữ liệu cho tùy chọn được chia sẻ và cam kết. Kiểm tra xem đầu vào của người dùng có bằng tùy chọn được chia sẻ mới hay không. Mặc dù tôi không thấy điều này khi cần thiết.

Và để đăng nhập các sự kiện này, chỉ cần thêm bạn Đăng nhập các dòng nếu có.

Ngoài ra, chỉ cần một lưu ý phụ, tôi không nghĩ rằng thực tế tốt để ném ngoại lệ nếu chúng không được đặt, tôi tin rằng quản lý luồng chương trình có thể được xử lý tốt hơn với các câu lệnh có điều kiện. một lỗi runtime. Lưu xử lý lỗi trong khi xác thực đầu vào của người dùng.

+0

Bạn đang nói về việc lưu kiểm tra thành công, nhưng tôi đang hỏi về việc lưu lý do thất bại. – Ircover

+0

@ Khám phá nếu bạn lo lắng về lý do không lưu được, mà tôi không nghĩ bạn cần, bạn có thể áp dụng logic tuần hoàn mà tôi đã đề cập. Đó là một kiểm tra đơn giản. Kiểm tra các giá trị đã nhập với các giá trị đã lưu gần đây, nếu chúng khác nhau, chúng không được cập nhật. –

+0

Logic của tôi là để ngăn chặn các vấn đề có thể ngăn chặn cam kết làm việc ngay từ đầu. Tôi đã tiếp cận toàn bộ vấn đề từ một quan điểm khác. Bạn có hiểu suy nghĩ của tôi không? Tôi đồng ý với câu trả lời khác, hãy kiểm soát cẩn thận nơi bạn thay đổi tùy chọn được chia sẻ của mình. –

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