Apa perbedaan antara commit () dan apply () di SharedPreferences

431

Saya menggunakan SharedPreferencesdi aplikasi android saya. Saya menggunakan keduanya commit()dan apply()metode dari preferensi bersama. Ketika saya menggunakan AVD 2.3 itu tidak menunjukkan kesalahan, tetapi ketika saya menjalankan kode di AVD 2.1, apply()metode menunjukkan kesalahan.

Jadi apa bedanya keduanya? Dan hanya dengan menggunakan commit()saya dapat menyimpan nilai preferensi tanpa masalah?

Andro Selva
sumber
115
Ini sudah berumur satu tahun, tetapi saya tetap akan mengomentarinya, meskipun mungkin sudah jelas, tidak ada jawaban yang menyatakan hal ini: apply()asynchronous melakukan disk I / O sementara commit()sinkron. Jadi Anda benar-benar tidak boleh menelepon commit()dari utas UI.
michiakig
Yang perlu diperhatikan, ketika beberapa objek SharedPreferences.Editor digunakan, yang terakhir dipanggil akan apply()menang. Oleh karena itu, Anda dapat menggunakan apply()sebagai pengganti commit()dengan aman jika Anda memastikan hanya satu SharedPreferences.Editor sedang digunakan oleh aplikasi Anda.
aoeu
2
Sesuai Android Studio Lint peringatan: commit () akan menyimpan data dengan segera dan secara sinkron. Namun, apply () akan menyimpannya secara tidak sinkron (di latar belakang) dan dengan demikian meningkatkan kinerja. Itulah mengapa berlaku () lebih disukai daripada komit () jika Anda tidak peduli dengan jenis pengembaliannya (Jika data berhasil disimpan atau tidak).
Rahul Raina
Apakah ada cara untuk menonaktifkan peringatan Lint saat menggunakan commit()?
QED

Jawaban:

653

apply()ditambahkan pada 2.3, ia melakukan tanpa mengembalikan boolean yang menunjukkan keberhasilan atau kegagalan.

commit()mengembalikan true jika save berfungsi, false sebaliknya.

apply() ditambahkan ketika tim pengembang Android memperhatikan bahwa hampir tidak ada yang memperhatikan nilai pengembalian, jadi aplikasinya lebih cepat karena asinkron.

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

Ray Britton
sumber
8
Jawaban ini benar tetapi saya kira komentar @spacemanaki di atas juga benar berisi informasi yang berharga
Aksel Fatih
58
commit () menulis datanya ke penyimpanan persisten segera, sedangkan apply () akan menanganinya di latar belakang.
capt.swag
18
apakah itu menciptakan kondisi balapan?
ChrisMcJava
42
Apa yang terjadi jika saya menulis sesuatu dengan apply () dan mencoba membacanya segera setelah itu? Apakah bacaan dijamin memberi saya nilai terbaru? Dokumen mengatakan jika komit lain () terjadi setelah Anda memecat berlaku (), komit itu () akan memblokir sampai berlaku () bertahan ke disk, yang membuatnya jelas bahwa masalah ini tidak terjadi ketika datang ke operasi 'tulis' , tetapi bagaimana jika Anda menulis dan membaca segera setelah itu? Dari pengujian saya, nilai terbaru dikembalikan, tetapi saya ingin tahu apakah ini dijamin 100% atau tidak.
Tiago
22
aman untuk mengganti setiap instance dari commit () dengan apply () lihat developer.android.com/reference/android/content/…
Tigran Sarkisian
221

tl; dr:

  • commit()menulis data secara sinkron (memblokir utasnya dari mana). Ini kemudian memberi tahu Anda tentang keberhasilan operasi.
  • apply()menjadwalkan data yang akan ditulis secara tidak sinkron . Itu tidak memberi tahu Anda tentang keberhasilan operasi.
  • Jika Anda menyimpan apply()dan segera membaca melalui metode getX apa pun, nilai baru akan dikembalikan!
  • Jika Anda menelepon apply()di beberapa titik dan itu masih dieksekusi, panggilan apa pun untuk commit()akan diblokir sampai semua panggilan-lalu melewati dan panggilan -komit saat ini selesai.

Informasi lebih mendalam dari SharedPreferences. Dokumentasi Pendukung :

Tidak seperti commit (), yang menulis preferensi ke penyimpanan persisten secara sinkron , terapkan () melakukan perubahan pada SharedPreferences di memori segera tetapi mulai komit asinkron ke disk dan Anda tidak akan diberitahu tentang kegagalan . Jika editor lain pada SharedPreferences ini melakukan komit () sementara berlaku () masih beredar, komit () akan memblokir sampai semua komit async selesai serta komit itu sendiri.

Karena instance SharedPreferences adalah lajang dalam suatu proses, aman untuk mengganti instance komit () dengan apply () jika Anda sudah mengabaikan nilai balik.

Antarmuka SharedPreferences.Editor tidak diharapkan untuk diterapkan secara langsung. Namun, jika sebelumnya Anda mengimplementasikannya dan sekarang mendapatkan kesalahan tentang missing apply (), Anda dapat memanggil commit () dari apply ().

Lukas Knuth
sumber
19
Ini adalah jawaban yang jauh lebih baik karena ia menyebutkan yang apply()tidak sinkron dan menunggu penulisan memblokir panggilan selanjutnya commit().
spaaarky21
22

Saya mengalami beberapa masalah dalam menggunakan apply (), bukan commit (). Seperti yang dinyatakan sebelumnya dalam respons lain, apply () asynchronous. Saya mendapatkan masalah bahwa perubahan yang dibentuk untuk preferensi "string set" tidak pernah ditulis ke memori persisten.

Itu terjadi jika Anda "memaksa penahanan" dari program atau, dalam ROM yang telah saya instal pada perangkat saya dengan Android 4.1, ketika prosesnya terbunuh oleh sistem karena kebutuhan memori.

Saya sarankan untuk menggunakan "commit ()" sebagai gantinya "apply ()" jika Anda ingin preferensi Anda tetap hidup.

JoseLSegura
sumber
Apakah Anda yakin masalah Anda tidak terkait karena threading bersamaan? Setelah Anda mengirim apply (), Anda harus menunggu beberapa saat untuk membaca hal-hal yang Anda tambahkan, jika tidak, utas UI akan berusaha membaca sebelum utas pekerja melamar () melakukan perubahan.
Marco Altran
Mengenai set string, stackoverflow.com/questions/16820252/…
Tapirboy
@JoseLSegura - dokumen menyarankan sebaliknya: developer.android.com/intl/ja/reference/android/content/… "Anda tidak perlu khawatir tentang siklus komponen Android dan interaksinya dengan menerapkan () menulis ke disk. Kerangka kerja memastikan disk dalam penerbangan menulis dari apply () selesai sebelum beralih status. " Saya bertanya-tanya apakah yang Anda lihat adalah bug di Android, dan jika demikian apakah itu telah diperbaiki di versi yang lebih baru.
ToolmakerSteve
Masalah yang sama terjadi pada saya menggunakan pustaka "ProcessPhoenix" untuk mengatur ulang aplikasi saya. Saya menyimpan preferensi sebelum melakukan reset, dan "berlaku" tidak berfungsi.
ElYeante
14

Gunakan apply ().

Itu menulis perubahan ke RAM segera dan menunggu dan menulisnya ke penyimpanan internal (file preferensi aktual) setelah. Komit menulis perubahan secara sinkron dan langsung ke file.

Mustafa
sumber
14
  • commit()sinkron, apply()asinkron

  • apply() adalah fungsi batal.

  • commit() mengembalikan true jika nilai-nilai baru berhasil ditulis ke penyimpanan persisten.

  • apply() jaminan selesai sebelum beralih status, Anda tidak perlu khawatir tentang siklus komponen Android

Jika Anda tidak menggunakan nilai yang dikembalikan dari commit()dan Anda menggunakan commit()dari utas utama, gunakan apply()sebagai ganti commit()

Nurlan Sofiyev
sumber
13

Dokumen memberikan penjelasan yang cukup bagus tentang perbedaan antara apply()dan commit():

Tidak seperti commit(), yang menulis preferensi ke penyimpanan persisten secara sinkron, apply()melakukan perubahan ke dalam memori SharedPreferencessegera tetapi memulai komit asinkron ke disk dan Anda tidak akan diberitahu tentang kegagalan. Jika editor lain SharedPreferencesmelakukan hal ini secara teratur commit()sementara a apply()masih beredar, commit()kehendak akan diblokir sampai semua async komit selesai serta komit itu sendiri. Karena SharedPreferencesinstance adalah lajang dalam suatu proses, aman untuk mengganti instance commit()dengan apply()jika Anda sudah mengabaikan nilai pengembalian.

Mojo Risin
sumber
6

Dari javadoc:

Tidak seperti komit (), yang menulis preferensi ke penyimpanan persisten secara sinkron, terapkan () lakukan perubahan pada SharedPreferences di memori segera tetapi mulai komit asinkron ke disk dan Anda tidak akan diberitahu tentang kegagalan. Jika editor lain pada SharedPreferences ini melakukan commit reguler () ketika> apply () masih beredar, komit () akan memblokir sampai semua commit async selesai serta komit itu sendiri

Vladimir Ivanov
sumber
1

Perbedaan antara commit () dan apply ()

Kita mungkin bingung dengan kedua istilah itu, ketika kita menggunakan SharedPreference. Pada dasarnya mereka mungkin sama, jadi mari kita perjelas perbedaan commit () dan apply ().

1.Return nilai:

apply()berkomitmen tanpa mengembalikan boolean yang menunjukkan keberhasilan atau kegagalan. commit() mengembalikan true jika save berfungsi, false sebaliknya.

  1. Kecepatan:

apply()lebih cepat. commit()lebih lambat.

  1. Asinkron vs Sinkron:

apply(): Asynchronous commit(): Synchronous

  1. Atom:

apply(): atom commit(): atom

  1. Pemberitahuan kesalahan:

apply(): Tidak commit(): Ya

Chanaka Weerasinghe
sumber
Bagaimana apply()"lebih cepat" daripada commit()? Mereka pada dasarnya mewakili tugas yang sama yang akan dimasukkan ke dalam Looper dari utas. commit()menempatkan tugas itu di Looper utama sambil apply()membawanya di latar belakang, sehingga menjaga looper utama bebas dari tugas I / O disk.
Taseer
Tidak seperti komit (), yang menulis preferensi ke penyimpanan persisten secara sinkron, terapkan () lakukan perubahan pada SharedPreferences di memori segera tetapi mulai komit asinkron ke disk dan Anda tidak akan diberitahu tentang kegagalan. Jika editor lain pada SharedPreferences ini melakukan commit reguler () ketika apply () masih beredar, komit () akan memblokir sampai semua commit async selesai dan juga komit itu sendiri melihat DOC developer.android.com/reference/ android / content / ...
Chanaka Weerasinghe