ความแตกต่างระหว่าง commit () และ Apply () ใน SharedPreferences


431

ฉันกำลังใช้งานSharedPreferencesในแอพ Android ของฉัน ฉันใช้ทั้งสองcommit()และapply()วิธีจากการตั้งค่าที่ใช้ร่วมกัน เมื่อฉันใช้ AVD 2.3 จะไม่แสดงข้อผิดพลาด แต่เมื่อฉันเรียกใช้รหัสใน AVD 2.1 apply()วิธีจะแสดงข้อผิดพลาด

ดังนั้นความแตกต่างระหว่างสองสิ่งนี้คืออะไร? และโดยใช้เพียงcommit()ฉันสามารถเก็บค่าการตั้งค่าโดยไม่มีปัญหาใด ๆ ?


115
นี่เป็นปี แต่ฉันจะแสดงความคิดเห็นต่อไปถึงแม้ว่ามันอาจจะเห็นได้ชัดไม่มีคำตอบใดที่ทำให้จุดนี้: apply()จะทำดิสก์ I / O แบบอะซิงโครนัสในขณะที่commit()ซิงโครนัส ดังนั้นคุณไม่ควรโทรcommit()จากเธรด UI
michiakig

จากบันทึกย่อเมื่อมีการใช้งาน SharedPreferences หลายออบเจ็กต์ตัวแก้ไขวัตถุตัวสุดท้ายที่จะเรียกใช้apply()จะชนะ ดังนั้นคุณสามารถใช้งานได้อย่างปลอดภัยapply()แทนcommit()หากคุณแน่ใจว่ามีการใช้งาน SharedPreferences เพียงแอปพลิเคชันเดียวเท่านั้น
aoeu

2
ตามคำเตือนของ Android Studio Lint: commit () จะบันทึกข้อมูลทันทีและพร้อมกัน อย่างไรก็ตาม Apply () จะบันทึกแบบอะซิงโครนัส (ในพื้นหลัง) และปรับปรุงประสิทธิภาพบางอย่าง นั่นคือเหตุผลที่ใช้ () เป็นที่ต้องการมากกว่ากระทำ () ถ้าคุณไม่สนใจประเภทผลตอบแทน (ถ้าข้อมูลถูกบันทึกเรียบร้อยแล้วหรือไม่)
ราหุลเรนนะ

มีวิธีปิดการใช้งานคำเตือนผ้าสำลีเมื่อใช้งานcommit()หรือไม่?
QED

คำตอบ:


653

apply()ถูกเพิ่มใน 2.3 มันกระทำโดยไม่ส่งคืนบูลีนเพื่อระบุว่าสำเร็จหรือล้มเหลว

commit()ผลตอบแทนจริงถ้าบันทึกงานเท็จอย่างอื่น

apply() ถูกเพิ่มเข้ามาเนื่องจากทีมนักพัฒนาซอฟต์แวร์ Android สังเกตเห็นว่าแทบจะไม่มีใครสังเกตเห็นว่ามีค่าส่งคืนดังนั้นการสมัครจึงเร็วขึ้นเพราะไม่ตรงกัน

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


8
คำตอบนี้เป็นจริง แต่ฉันเดาว่าความคิดเห็นของ @spacemanaki ด้านบนยังเป็นจริงซึ่งมีข้อมูลที่มีค่า
Aksel Fatih

58
กระทำ () เขียนข้อมูลไปยังที่เก็บข้อมูลถาวรทันทีในขณะที่ใช้ () จะจัดการกับมันในพื้นหลัง
capt.swag

18
มันสร้างสภาพการแข่งขันหรือไม่?
ChrisMcJava

42
จะเกิดอะไรขึ้นถ้าฉันเขียนบางสิ่งด้วย Apply () และลองอ่านทันทีหลังจากนั้น การอ่านรับประกันว่าจะให้ค่าใหม่ล่าสุดแก่ฉันหรือไม่? เอกสารบอกว่ามีการกระทำอื่น () เกิดขึ้นหลังจากที่คุณเริ่มใช้ () การกระทำนั้น () จะปิดกั้นจนกว่าการใช้ () จะยังคงอยู่บนดิสก์ซึ่งทำให้ชัดเจนว่าปัญหานี้จะไม่เกิดขึ้นเมื่อดำเนินการ 'เขียน' แต่ถ้าคุณเขียนและอ่านทันทีหลังจากนั้นล่ะ จากการทดสอบของฉันจะส่งคืนค่าใหม่ล่าสุด แต่ฉันต้องการทราบว่าสิ่งนี้รับประกันได้ 100% หรือไม่
Tiago

22
มันปลอดภัยที่จะแทนที่อินสแตนซ์ใด ๆ ของ commit () ด้วย Apply () ดูdeveloper.android.com/reference/android/content/ …
Tigran Sarkisian

221

TL; DR:

  • commit()เขียนข้อมูลแบบซิงโครนัส (บล็อกเธรดที่เรียกจาก) จากนั้นจะแจ้งให้คุณทราบเกี่ยวกับความสำเร็จของการดำเนินการ
  • apply()ตารางข้อมูลที่จะเขียนถ่ายทอดสด มันไม่ได้แจ้งให้คุณทราบเกี่ยวกับความสำเร็จของการดำเนินการ
  • หากคุณบันทึกด้วยapply()และอ่านผ่านเมธอด getX ทันทีค่าใหม่จะถูกส่งคืน!
  • หากคุณโทรไปapply()ที่จุดใดจุดหนึ่งและยังคงดำเนินการอยู่การโทรใด ๆ ที่commit()จะบล็อกจนกว่าจะใช้การโทรทั้งหมดที่ผ่านมาและการรับสายปัจจุบันเสร็จสิ้น

ข้อมูลเชิงลึกเพิ่มเติมจากSharedPreferencesเอกสารคู่มือผู้ใช้ :

ซึ่งแตกต่างจากการกระทำ () ซึ่งเขียนการตั้งค่าออกไปยังที่เก็บถาวรพร้อมกัน , ใช้ () กระทำการเปลี่ยนแปลงในการ SharedPreferences ในหน่วยความจำได้ทันที แต่เริ่มไม่ตรงกันกระทำไปยังดิสก์และคุณจะไม่ได้รับการแจ้งเตือนของความล้มเหลวใด หากตัวแก้ไขอื่นใน SharedPreferences นี้ทำการคอมมิทปกติ () ในขณะที่การใช้ () ยังคงค้างอยู่คอมมิชชัน () จะบล็อกจนกว่าการคอมมิท async ทั้งหมดจะเสร็จสิ้นและการคอมมิทเอง

เนื่องจากอินสแตนซ์ของ SharedPreferences เป็นซิงเกิลภายในกระบวนการจึงปลอดภัยที่จะแทนที่อินสแตนซ์การส่งมอบ () ใด ๆ ด้วยการใช้ () หากคุณไม่สนใจค่าส่งคืน

SharedPreferences.Editor ไม่คาดว่าจะนำมาใช้โดยตรง อย่างไรก็ตามหากก่อนหน้านี้คุณได้ติดตั้งแล้วและตอนนี้ได้รับข้อผิดพลาดเกี่ยวกับการใช้ที่หายไป () คุณสามารถเรียกการยอมรับ () จากการใช้ ()


19
นี่คือคำตอบที่ดีมากเพราะมันกล่าวว่าไม่ตรงกันและเขียนอยู่ระหว่างดำเนินการป้องกันการโทรในอนาคตapply() commit()
spaaarky21

22

ฉันประสบปัญหาบางอย่างในการใช้ Apply () แทนที่จะกระทำ () ตามที่ระบุไว้ก่อนในการตอบสนองอื่น ๆ นำไปใช้ () เป็นแบบอะซิงโครนัส ฉันพบปัญหาว่าการเปลี่ยนแปลงที่เกิดขึ้นกับการตั้งค่า "ชุดสตริง" ไม่เคยถูกเขียนลงในหน่วยความจำถาวร

มันจะเกิดขึ้นหากคุณ "บังคับให้กักตัว" ของโปรแกรมหรือใน ROM ที่ฉันติดตั้งบนอุปกรณ์ของฉันกับ Android 4.1 เมื่อกระบวนการถูกฆ่าโดยระบบเนื่องจากความจำเป็นของหน่วยความจำ

ฉันแนะนำให้ใช้ "commit ()" แทน "Apply ()" ถ้าคุณต้องการความพึงพอใจของคุณ


คุณแน่ใจหรือว่าปัญหาของคุณไม่เกี่ยวข้องเนื่องจากเธรดพร้อมกัน? หลังจากที่คุณส่งการใช้ () คุณต้องรอสักครู่เพื่ออ่านสิ่งที่คุณเพิ่มมิฉะนั้นเธรด UI จะพยายามอ่านก่อนที่เธรดการทำงานของผู้ใช้ () จะยอมรับการเปลี่ยนแปลง
Marco Altran

เกี่ยวกับชุดสตริงstackoverflow.com/questions/16820252//
Tapirboy

@JoseLSegura - เอกสารแนะนำเป็นอย่างอื่น: developer.android.com/intl/ja/reference/android/content/… "คุณไม่จำเป็นต้องกังวลเกี่ยวกับวงจรชีวิตของอุปกรณ์ Android และการโต้ตอบกับพวกเขาด้วยการใช้ () เขียนลงบนดิสก์กรอบงาน ทำให้แน่ใจว่าการเขียนดิสก์ในเที่ยวบินจากการใช้ () เสร็จสมบูรณ์ก่อนที่จะเปลี่ยนสถานะ " ฉันสงสัยว่าสิ่งที่คุณเห็นเป็นข้อบกพร่องใน Android หรือไม่และถ้าเป็นเช่นนั้นจะได้รับการแก้ไขในเวอร์ชันที่ใหม่กว่าหรือไม่
ToolmakerSteve

ปัญหาเดียวกันนี้เกิดขึ้นกับฉันโดยใช้ห้องสมุด "ProcessPhoenix" เพื่อรีเซ็ตแอปของฉัน ฉันบันทึกค่ากำหนดก่อนทำการรีเซ็ตและ "ใช้" ไม่ทำงาน
ElYeante

14

ใช้ใช้ ()

มันเขียนการเปลี่ยนแปลงไปยัง RAM ทันทีและรอและเขียนลงในที่จัดเก็บข้อมูลภายใน (ไฟล์การตั้งค่าที่แท้จริง) หลังจากนั้น Commit เขียนการเปลี่ยนแปลงแบบซิงโครนัสและตรงไปยังไฟล์


14
  • commit()เป็นapply()แบบซิงโครนัสแบบอะซิงโครนัส

  • apply() ฟังก์ชั่นเป็นโมฆะ

  • commit() ผลตอบแทนจริงถ้าค่าใหม่ถูกเขียนไปยังการจัดเก็บถาวร

  • apply() รับประกันเสร็จสมบูรณ์ก่อนที่จะเปลี่ยนสถานะคุณไม่ต้องกังวลเกี่ยวกับวงจรชีวิตของอุปกรณ์ Android

หากคุณไม่ใช้ค่าที่ส่งคืนจากcommit()และคุณกำลังใช้commit()จากเธรดหลักให้ใช้apply()แทน commit()


13

เอกสารให้คำอธิบายที่ดีเกี่ยวกับความแตกต่างระหว่างapply()และcommit():

ซึ่งแตกต่างจากcommit()ที่เขียนการตั้งค่าออกไปยังที่เก็บข้อมูลถาวรพร้อมกันapply()กระทำการเปลี่ยนแปลงในหน่วยความจำ SharedPreferencesทันที แต่เริ่มต้นการกระทำแบบอะซิงโครนัสไปยังดิสก์และคุณจะไม่ได้รับแจ้งจากความล้มเหลวใด ๆ หากตัวแก้ไขอื่นทำสิ่งนี้SharedPreferencesเป็นประจำcommit()ในขณะที่ a apply()ยังคงค้างอยู่commit()จะบล็อกจนกว่าการคอมมิทของ async ทั้งหมดจะเสร็จสิ้นและการคอมมิทตัวเอง เนื่องจากSharedPreferencesอินสแตนซ์นั้นเป็นซิงเกิลตันภายในกระบวนการจึงปลอดภัยที่จะแทนที่อินสแตนซ์ใด ๆ commit()ด้วยapply()ถ้าคุณไม่สนใจค่าส่งคืน


6

จาก javadoc:

ซึ่งแตกต่างจากการกระทำ () ซึ่งเขียนการตั้งค่าของมันออกไปยังที่เก็บข้อมูลถาวรพร้อมกันนำไปใช้ () กระทำการเปลี่ยนแปลงใน SharedPreferences ในหน่วยความจำทันที แต่เริ่มการคอมมิชชันแบบอะซิงโครนัสลงดิสก์และคุณจะไม่ได้รับแจ้ง หากตัวแก้ไขอื่นใน SharedPreferences นี้ทำการคอมมิทปกติ () ในขณะที่> Apply () ยังคงค้างอยู่คอมมิชชัน () จะบล็อกจนกว่าการคอมมิท async ทั้งหมดจะเสร็จสมบูรณ์เช่นเดียวกับการคอมมิทเอง


1

ความแตกต่างระหว่างการกระทำ () และนำไปใช้ ()

เราอาจสับสนกับคำสองคำนี้เมื่อเราใช้ SharedPreference โดยพื้นฐานแล้วพวกเขาอาจจะเหมือนกันดังนั้นขออธิบายความแตกต่างของการกระทำ () และใช้ ()

1. มูลค่าส่งคืน:

apply()กระทำโดยไม่ส่งคืนบูลีนที่ระบุถึงความสำเร็จหรือความล้มเหลว commit() ผลตอบแทนจริงถ้าบันทึกงานเท็จอย่างอื่น

  1. ความเร็ว:

apply()เร็วกว่า. commit()ช้ากว่า

  1. อะซิงโครนัส vs ซิงโครนัส:

apply(): Asynchronous commit(): ซิงโคร

  1. อะตอม:

apply(): อะตอม commit(): อะตอม

  1. การแจ้งเตือนข้อผิดพลาด:

apply(): ไม่ commit(): ใช่


เป็นวิธีการที่apply()"เร็วขึ้น" กว่าcommit()? พวกเขาเป็นตัวแทนของงานเดียวกันที่จะใส่ใน Looper ของด้าย commit()วางงานนั้นไว้ใน Looper หลักขณะที่ทำงานapply()บนพื้นหลังจึงทำให้ Looper หลักไม่ทำงานของดิสก์ I / O
Taseer

ซึ่งแตกต่างจากการกระทำ () ซึ่งเขียนการตั้งค่าของมันออกไปยังที่เก็บข้อมูลถาวรพร้อมกันนำไปใช้ () กระทำการเปลี่ยนแปลงใน SharedPreferences ในหน่วยความจำทันที แต่เริ่มการคอมมิชชันแบบอะซิงโครนัสลงดิสก์และคุณจะไม่ได้รับการแจ้งเตือน หากตัวแก้ไขอื่นใน SharedPreferences นี้มีการกระทำปกติ () ในขณะที่การใช้ () ยังคงค้างอยู่การกระทำ () จะบล็อกจนกว่าการคอมมิท async ทั้งหมดจะเสร็จสมบูรณ์รวมถึงการคอมมิชชันเองจะเห็น DOC developer.android.com/reference/ android / content / …
Chanaka Weerasinghe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.