Яка різниця між commit () та застосувати () у SharedPreferences


431

Я використовую SharedPreferencesв додатку для Android. Я використовую і те, commit()і apply()метод із загальних уподобань. Коли я використовую AVD 2.3, він не показує помилок, але коли я запускаю код в AVD 2.1, apply()метод показує помилку.

То яка різниця між цими двома? І тільки використовуючи, чи commit()можу я зберігати значення переваг без проблем?


115
Цього року, але я все-таки прокоментую це, хоча це може бути очевидним, жодна з відповідей не вказує на це: apply()буде асинхронно робити введення / виведення диска, поки воно commit()буде синхронним. Таким чином, ви дійсно не повинні дзвонити commit()з потоку інтерфейсу користувача.
michiakig

Зверніть увагу, коли використовується декілька об'єктів SharedPreferences.Editor, останній, хто дзвонить, apply()виграє. Таким чином, ви можете використовувати apply()замість commit()безпечного, якщо ви переконаєтесь, що вашим додатком використовується лише один SharedPreferences.Editor.
aoeu

2
Відповідно до попередження Android Studio Lint: commit () збереже дані негайно та синхронно. Однак, застосування () дозволить зберегти його асинхронно (на задньому плані) і тим самим підвищити деяку ефективність. Ось чому застосовувати () є кращим перед віддаленням (), якщо ви не переймаєтесь його типом повернення (якщо дані збережено успішно чи ні).
Рахул Райна

Чи є спосіб відключити попередження Lint під час використання commit()?
QED

Відповіді:


653

apply()Додано в 2.3, він здійснює, не повертаючи булевого сигналу, що вказує на успіх чи невдачу.

commit()повертає true, якщо збереження працює, false в іншому випадку.

apply() Додано, як команда Android Dev помітила, що майже ніхто не помітив поверненого значення, тому застосувати швидше, оскільки це асинхронно.

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


8
Ця відповідь правдива, але, мабуть, коментар @spacemanaki вище також правдивий, містить цінну інформацію
Аксель Фатих

58
commit () записує свої дані в постійне зберігання негайно, тоді як apply () обробляє їх у фоновому режимі.
capt.swag

18
чи створює це стан перегонів?
ChrisMcJava

42
Що станеться, якщо я щось напишу за допомогою Apply () і спробую прочитати це відразу після? Чи гарантоване читання дасть мені новітнє значення? Документи говорять, що якщо інша фіксація () відбудеться після того, як ви запустили, застосуйте (), що фіксація () заблокується, поки на диску не збережеться застосувати (), що дає зрозуміти, що ця проблема не виникає, коли мова йде про операції "запису". , а як бути, якщо ви пишете і читаєте відразу після цього? З моїх тестів повертається найновіше значення, але я хочу знати, гарантовано це на 100% чи ні.
Тіаго

22
безпечно замінити будь-який примірник комісії () на apply (), див. developer.android.com/reference/android/content/…
Tigran Sarkisian

221

tl; dr:

  • commit()записує дані синхронно (блокуючи потік її виклику з). Потім він повідомляє вас про успіх операції.
  • apply()планує записувати дані асинхронно . Це не інформує вас про успіх операції.
  • Якщо ви збережете за допомогою apply()та негайно прочитаєте будь-який метод getX, нове значення повернеться!
  • Якщо ви зателефонували apply()в якийсь момент, і він все ще виконується, будь-які дзвінки commit()блокуватимуться, поки всі попередні виклики подачі заявки та поточний виклик на завершення не завершиться.

Більш поглиблена інформація з документації SharedPreferences.Editor :

На відміну від commit (), який записує свої переваги для постійного зберігання синхронно , application () негайно здійснює свої зміни в пам'яті SharedPreferences, але запускає асинхронну передачу на диск, і вам не повідомлять про будь-які збої . Якщо інший редактор у цій SharedPreferences виконує регулярне виконання (), тоді як застосунок () все ще залишається невиконаним, команда commit () блокується, поки не будуть виконані всі асинхронні комісії, а також сама фіксація.

Оскільки екземпляри SharedPreferences є одинаковими в процесі, безпечно замінити будь-який примірник commit () на apply (), якщо ви вже ігнорували повернене значення.

Не очікується, що інтерфейс SharedPreferences.Editor буде реалізований безпосередньо. Однак якщо раніше ви його реалізували і тепер отримуєте помилки щодо відсутнього apply (), ви можете просто зателефонувати на комісію commit () від apply ().


19
Це набагато краща відповідь, оскільки вона згадує про apply()асинхронність і очікує на запис блоку майбутніх викликів commit().
spaaarky21

22

У мене виникають проблеми із застосуванням Apply (), а не commit (). Як зазначено раніше в інших відповідях, application () є асинхронним. У мене виникає проблема, що зміни, сформовані в налаштуваннях набору рядків, ніколи не записуються в стійку пам'ять.

Це трапляється, якщо ви «змушуєте затримувати» програму або, якщо я встановив на ПЗУ, який я встановив на свій пристрій під керуванням Android 4.1, коли процес вбивається системою через потреби в пам’яті.

Рекомендую замість цього "Apply ()" застосувати () ", якщо ви хочете, щоб ваші налаштування були активними.


Ви впевнені, що ваша проблема не пов'язана з одночасним нарізанням різьби? Після відправлення apply (), вам доведеться почекати деякий час, щоб прочитати додані вами речі, інакше потік інтерфейсу спробує прочитати, перш ніж робочий потік application () вчинив зміни.
Марко Алтран

Що стосується рядки набору, stackoverflow.com/questions/16820252 / ...
Tapirboy

@JoseLSegura - Документи пропонують інакше: developer.android.com/intl/ja/reference/android/content/… "Вам не потрібно турбуватися про життєві цикли компонентів Android та їх взаємодію із записом на застосуванні () на диск. Рамка переконайтеся, що запис на диску на польоті з параметра Apply () завершено перед переключенням у стан. Мені цікаво, якщо ви бачите помилку в Android, і якщо так, чи виправлено це в нових версіях.
ToolmakerSteve

Сама ж проблема сталася зі мною за допомогою бібліотеки "ProcessPhoenix" для скидання програми. Я зберігав налаштування безпосередньо перед тим, як виконати скидання, і "застосувати" не працює.
ElYeante

14

Використовуйте Apply ().

Він записує зміни в ОЗУ негайно і чекає і записує їх у внутрішню пам’ять (фактичний файл переваг) після. Комунікація записує зміни синхронно та безпосередньо у файл.


14
  • commit()є синхронним, apply()є асинхронним

  • apply() недійсна функція.

  • commit() повертає істину, якщо нові значення були успішно записані в постійне зберігання.

  • apply() гарантує повне перед переключенням станів, вам не потрібно хвилюватися про життєві цикли компонентів Android

Якщо ви не використовуєте значення , повернутого commit()і ви використовуєте commit()від основного потоку, використовуйте apply()замість commit()


13

Документи дають досить хороше пояснення різниці між apply()та commit():

На відміну від того commit(), що записує свої налаштування на постійне зберігання синхронно, негайно apply()здійснює свої зміни в пам’яті, SharedPreferencesале запускає асинхронну передачу на диск і вам не повідомлять про будь-які збої. Якщо інший редактор цього запису SharedPreferencesробить звичайним, commit()поки a apply()все ще залишається непогашеним, commit()блокування буде заблоковано, поки всі асинхронні зобов’язання не будуть виконані, а також сама фіксація. Як SharedPreferencesекземпляри одноелементна всередині процесу, це безпечно замінити будь-який екземпляр commit()з , apply()якщо ви вже НЕ звертаючи уваги на значення, що повертається.


6

Від javadoc:

На відміну від commit (), який записує свої налаштування на стійке зберігання синхронно, application () негайно здійснює свої зміни в пам'яті SharedPreferences, але запускає асинхронну передачу на диск, і вам не повідомлять про будь-які збої. Якщо інший редактор у цій SharedPreferences виконує регулярний фіксатор (), тоді як a> apply () все ще залишається невирішеним, commit () блокується, поки всі асинхронні комісії не будуть виконані, а також сама фіксація.


1

Різниця між комісіями () та застосувати ()

Ці два терміни можуть нас збентежити, коли ми використовуємо SharedPreference. В основному вони, ймовірно, однакові, тому давайте уточнимо відмінності фіксування () та застосуємо ().

1.Важливість повернення:

apply()здійснює без повернення булевого сигналу, що вказує на успіх чи невдачу. commit() повертає true, якщо збереження працює, false інше.

  1. Швидкість:

apply()швидше. commit()повільніше.

  1. Асинхронний проти синхронний:

apply(): Асинхронний commit(): Синхронний

  1. Атомний:

apply(): атомний commit(): атомний

  1. Повідомлення про помилку:

apply(): Ні commit(): Так


Як apply()"швидше", ніж commit()? Вони по суті являють собою те саме завдання, яке було б поставлено в Looper нитки. commit()ставить це завдання в основний Looper, тоді як apply()знімає його на задньому плані, тим самим зберігаючи головний петлюр без дискового завдання вводу / виводу.
Тасіір

На відміну від commit (), який записує свої переваги для постійного зберігання синхронно, application () негайно здійснює свої зміни в пам'яті SharedPreferences, але запускає асинхронну передачу на диск, і вам не повідомлять про будь-які збої. Якщо інший редактор у цій SharedPreferences виконує звичайний фіксатор (), поки застосований () ще залишається невирішеним, комікс () блокується, поки всі асинхронні комісії не будуть виконані, а також сама комісія перегляне розробник
Chanaka Weerasinghe
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.