Sự khác biệt giữa commit () và áp dụng () trong SharedPreferences


432

Tôi đang sử dụng SharedPreferencestrong ứng dụng Android của tôi. Tôi đang sử dụng cả haicommit()apply()phương pháp từ sở thích được chia sẻ. Khi tôi sử dụng AVD 2.3, nó không có lỗi, nhưng khi tôi chạy mã trong AVD 2.1, apply()phương thức hiển thị lỗi.

Vậy sự khác biệt giữa hai điều này là gì? Và bằng cách sử dụng chỉ commit()tôi có thể lưu trữ giá trị ưu tiên mà không có bất kỳ vấn đề?


115
Đây là một năm tuổi, nhưng dù sao tôi cũng sẽ bình luận về nó, mặc dù có thể rõ ràng, không có câu trả lời nào đưa ra quan điểm này: apply()sẽ không đồng bộ làm I / O đĩa trong khi commit()đồng bộ. Vì vậy, bạn thực sự không nên gọi commit()từ luồng UI.
michiakig

Đáng lưu ý, khi nhiều đối tượng SharedPreferences.Editor được sử dụng, đối tượng cuối cùng để gọi apply()chiến thắng. Do đó, bạn có thể sử dụng apply()thay cho commit()an toàn nếu bạn đảm bảo chỉ có một SharedPreferences.Editor đang được ứng dụng của bạn sử dụng.
aoeu

2
Theo cảnh báo Lint của Android Studio: commit () sẽ lưu dữ liệu ngay lập tức và đồng bộ. Tuy nhiên, áp dụng () sẽ lưu nó không đồng bộ (trong nền) và do đó cải thiện một số hiệu suất. Đó là lý do tại sao áp dụng () được ưu tiên hơn so với cam kết () nếu bạn không quan tâm đến kiểu trả về của nó (Nếu dữ liệu được lưu thành công hay không).
Rahul Raina

Có cách nào để tắt cảnh báo Lint khi sử dụng commit()không?
QED

Câu trả lời:


654

apply()đã được thêm vào trong 2.3, nó cam kết mà không trả về boolean cho thấy thành công hay thất bại.

commit()trả về true nếu lưu hoạt động, sai khác.

apply() đã được thêm vào khi nhóm nhà phát triển Android nhận thấy rằng hầu như không ai chú ý đến giá trị trả về, vì vậy việc áp dụng sẽ nhanh hơn vì nó không đồng bộ.

http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#apply ()


8
Câu trả lời này là đúng nhưng tôi đoán nhận xét của @spacemanaki ở trên cũng đúng có chứa thông tin có giá trị
Aksel Fatih

58
commit () ghi dữ liệu của nó vào bộ lưu trữ liên tục ngay lập tức, trong khi áp dụng () sẽ xử lý nó trong nền.
capt.swag

18
nó tạo ra một điều kiện chủng tộc?
ChrisMcJava

42
Điều gì xảy ra nếu tôi viết một cái gì đó với áp dụng () và cố gắng đọc nó ngay sau đó? Là đọc đảm bảo để cung cấp cho tôi giá trị mới nhất? Các tài liệu nói rằng nếu một xác nhận () khác xảy ra sau khi bạn bắn áp dụng (), thì cam kết () đó sẽ chặn cho đến khi áp dụng () được duy trì vào đĩa, điều này cho thấy rõ vấn đề này không xảy ra khi hoạt động 'ghi' , nhưng nếu bạn đang viết và đọc ngay sau đó thì sao? Từ các thử nghiệm của tôi, giá trị mới nhất được trả về, nhưng tôi muốn biết liệu điều này có được đảm bảo 100% hay không.
Tiago

22
an toàn để thay thế bất kỳ trường hợp nào của commit () bằng áp dụng () xem developer.android.com/reference/android/content/
mẹo

221

tl; dr:

  • commit()ghi dữ liệu một cách đồng bộ (chặn luồng được gọi từ). Sau đó nó thông báo cho bạn về sự thành công của hoạt động.
  • apply()lập lịch trình dữ liệu được viết không đồng bộ . Nó không thông báo cho bạn về sự thành công của hoạt động.
  • Nếu bạn lưu với apply()đọc ngay lập tức thông qua bất kỳ phương thức getX nào, giá trị mới sẽ được trả về!
  • Nếu bạn đã gọi apply()tại một số điểm và nó vẫn đang thực hiện, mọi cuộc gọi đến commit()sẽ bị chặn cho đến khi tất cả các cuộc gọi áp dụng trong quá khứ cuộc gọi cam kết hiện tại kết thúc.

Thông tin chi tiết hơn từ SharedPreferences.Editor Tài liệu:

Không giống như commit (), ghi các tùy chọn của nó vào bộ lưu trữ liên tục một cách đồng bộ , áp dụng () cam kết các thay đổi của nó đối với SharedPreferences trong bộ nhớ ngay lập tức nhưng bắt đầu một cam kết không đồng bộ vào đĩa và bạn sẽ không được thông báo về bất kỳ lỗi nào . Nếu một trình soạn thảo khác trên SharedPreferences thực hiện một cam kết thông thường () trong khi ứng dụng () vẫn còn tồn tại, thì cam kết () sẽ chặn cho đến khi tất cả các cam kết không đồng bộ được hoàn thành cũng như chính cam kết đó.

Vì các phiên bản SharedPreferences là các singletons trong một tiến trình, nên việc thay thế bất kỳ trường hợp nào của commit () bằng áp dụng () là an toàn nếu bạn đã bỏ qua giá trị trả về.

Giao diện SharedPreferences.Editor dự kiến ​​sẽ không được triển khai trực tiếp. Tuy nhiên, nếu trước đây bạn đã thực hiện nó và hiện đang gặp lỗi về thiếu áp dụng (), bạn chỉ cần gọi commit () từ application ().


19
Đây là một câu trả lời tốt hơn nhiều vì nó đề cập đến việc apply()không đồng bộ và đang chờ xử lý ghi các cuộc gọi trong tương lai commit().
spaaarky21

22

Tôi đang gặp một số vấn đề khi sử dụng áp dụng () thay vì commit (). Như đã nêu trước đây trong các phản hồi khác, áp dụng () là không đồng bộ. Tôi đang gặp vấn đề là những thay đổi được hình thành theo sở thích "tập hợp chuỗi" không bao giờ được ghi vào bộ nhớ liên tục.

Nó xảy ra nếu bạn "bắt giữ" chương trình hoặc, trong ROM mà tôi đã cài đặt trên thiết bị của mình với Android 4.1, khi quá trình này bị hệ thống giết chết do nhu cầu bộ nhớ.

Tôi khuyên bạn nên sử dụng "commit ()" thay vì "áp dụng ()" nếu bạn muốn sở thích của mình còn sống.


Bạn có chắc chắn vấn đề của bạn không liên quan do phân luồng đồng thời? Sau khi bạn gửi áp dụng (), bạn phải đợi một lúc để đọc những thứ bạn đã thêm, nếu không, luồng UI sẽ cố đọc trước khi luồng worker của application () cam kết các thay đổi.
Marco Altran


@JoseLSegura - các tài liệu đề xuất khác: developer.android.com/intl/ja/reference/android/content/ trộm "Bạn không cần phải lo lắng về vòng đời thành phần Android và tương tác của chúng với việc ghi () vào đĩa. đảm bảo đĩa trong chuyến bay ghi từ áp dụng () hoàn thành trước khi chuyển trạng thái. " Tôi tự hỏi liệu những gì bạn đang thấy có phải là một lỗi trong Android hay không và liệu nó có được sửa trong các phiên bản mới hơn không.
ToolmakerSteve

Vấn đề tương tự xảy ra với tôi khi sử dụng thư viện "ProcessPhoenix" để thiết lập lại ứng dụng của mình. Tôi đã lưu tùy chọn ngay trước khi thực hiện đặt lại và "áp dụng" không hoạt động.
ElYeante

14

Sử dụng áp dụng ().

Nó ghi các thay đổi vào RAM ngay lập tức và chờ và ghi nó vào bộ nhớ trong (tệp ưu tiên thực tế) sau đó. Cam kết ghi các thay đổi đồng bộ và trực tiếp vào tệp.


14
  • commit()là đồng bộ, apply()không đồng bộ

  • apply() là hàm void.

  • commit() trả về true nếu các giá trị mới được ghi thành công vào bộ lưu trữ liên tục.

  • apply() đảm bảo hoàn thành trước khi chuyển trạng thái, bạn không cần lo lắng về vòng đời thành phần Android

Nếu bạn không sử dụng giá trị được trả về từ commit()và bạn đang sử dụng commit()từ luồng chính, hãy sử dụng apply()thay vì commit()


13

Các tài liệu đưa ra một lời giải thích khá tốt về sự khác biệt giữa apply()commit():

Không giống như commit(), ghi các tùy chọn của nó vào bộ lưu trữ liên tục một cách đồng bộ, apply()cam kết các thay đổi của nó đối với bộ nhớ trong SharedPreferencesngay lập tức nhưng bắt đầu một cam kết không đồng bộ vào đĩa và bạn sẽ không được thông báo về bất kỳ lỗi nào. Nếu một trình soạn thảo khác về điều này SharedPreferencesthực hiện thường xuyên commit()trong khi a apply()vẫn còn tồn tại, thì commit()sẽ chặn cho đến khi tất cả các cam kết async được hoàn thành cũng như chính cam kết. Như SharedPreferencestrường hợp là độc thân trong một quá trình, nó an toàn để thay thế bất kỳ trường hợp commit()với apply()nếu bạn đã được bỏ qua các giá trị trả về.


6

Từ javadoc:

Không giống như commit (), ghi các tùy chọn của nó vào bộ lưu trữ liên tục một cách đồng bộ, áp dụng () cam kết các thay đổi của nó đối với SharedPreferences trong bộ nhớ ngay lập tức nhưng bắt đầu một cam kết không đồng bộ vào đĩa và bạn sẽ không được thông báo về bất kỳ lỗi nào. Nếu một trình soạn thảo khác trên SharedPreferences này thực hiện một cam kết thông thường () trong khi a> áp dụng () vẫn còn tồn tại, thì cam kết () sẽ chặn cho đến khi tất cả các cam kết async được hoàn thành cũng như chính cam kết


1

Sự khác biệt giữa commit () và áp dụng ()

Chúng tôi có thể bị nhầm lẫn bởi hai thuật ngữ đó, khi chúng tôi đang sử dụng SharedPreference. Về cơ bản chúng có thể giống nhau, vì vậy hãy làm rõ sự khác biệt của commit () và áp dụng ().

1. Giá trị hoàn trả:

apply()cam kết mà không trả lại một boolean cho thấy thành công hay thất bại. commit() trả về true nếu lưu hoạt động, sai khác.

  1. Tốc độ:

apply()nhanh hơn. commit()chậm hơn

  1. Không đồng bộ vs Đồng bộ:

apply(): Không đồng bộ commit(): Đồng bộ

  1. Nguyên tử:

apply(): nguyên tử commit(): nguyên tử

  1. Thông báo lỗi:

apply(): Không commit(): Vâng


Làm thế nào là apply()"nhanh" hơn commit()? Chúng cơ bản đại diện cho một nhiệm vụ tương tự sẽ được đưa vào Looper của luồng. commit()đặt nhiệm vụ đó trong Looper chính trong khi apply()đưa nó lên nền, do đó giữ cho looper chính không có nhiệm vụ I / O trên đĩa.
Taseer

Không giống như commit (), ghi các tùy chọn của nó vào bộ lưu trữ liên tục một cách đồng bộ, áp dụng () cam kết các thay đổi của nó đối với SharedPreferences trong bộ nhớ ngay lập tức nhưng bắt đầu một cam kết không đồng bộ vào đĩa và bạn sẽ không được thông báo về bất kỳ lỗi nào. Nếu một trình soạn thảo khác trên SharedPreferences thực hiện một cam kết thông thường () trong khi ứng dụng () vẫn còn tồn tại, thì cam kết () sẽ chặn cho đến khi tất cả các cam kết async được hoàn thành cũng như chính cam kết đó sẽ thấy nhà phát triển
Bắn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.