傻傻分不清楚系列(一):SharedPreferences的commit和apply方法
一、簡介
在開發中,很多重要的瞬時資料都需要儲存起來讓資料持久化,即 Android 中的資料持久化技術。相信這個對於大家來說並不陌生,常用的如檔案儲存、資料庫儲存、SharedPreferences ,以及網路儲存等。今天要介紹的便是其中之一的 SharedPreferences 。
SharedPreferences 是一個輕量級的儲存類,常用於儲存軟體配置引數、賬號和密碼等。SharedPreferences 內部使用 xml 檔案將資料以 key...value 的格式儲存在 “\data\data\應用程式包名\shared_prefs\” 目錄下,在 Android Studio 中開啟 Device File Explorer 即可檢視。下圖是 SharedPreferences 可以儲存的資料型別。
接下來是實踐時間,分別介紹利用 SharedPreferences 存資料和取資料的方法。
二、用法
(一)SharedPreferences 存資料
- 獲取 SharedPreferences 物件。Android 中提供了三種方法獲取 SharedPreferences 物件:
- Context 類中的 getSharedPreferences() 方法
/**
* Activity中直接getSharedPreferences,Fragment中需要getActivity().getSharedPreferences
* 引數一:SharedPreferences檔名
* 引數二:操作模式,Android6.0之後僅MODE_PRIVATE一種模式可選,表示只有當前應用程式才能對引數①中的檔案進行讀寫
*/
SharedPreferences sp = getSharedPreferences("user_info", MODE_PRIVATE);
- Activity 類中的 getPreferences() 方法
/**
* Activity中直接getPreferences,Fragment中需要getActivity().getPreferences()
* 引數:操作模式(此種方式獲取SharedPreferences物件時會自動使用當前Activity的類名作為檔名,所以只需一個引數)
*/
SharedPreferences sp = getPreferences(MODE_PRIVATE);
- PreferencesManager 類中的 getDefaultSharedPreferences() 方法
/**
* PreferenceManager類的靜態方法,自動使用當前應用程式包名作為字首來命名SharedPreferences檔案,操作模式自動為MODE_PRIVATE
* 引數:上下文
*/
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
- 呼叫 SharedPreferences 物件的 edit() 方法獲取 SharedPreferences.Editor 物件:
SharedPreferences.Editor editor = sp.edit();
- 呼叫 SharedPreferences.Editor 物件的 putXXX() 方法新增需要儲存的資料:
Set<String> userInfo = new HashSet<>();
userInfo.add("張三");
userInfo.add("20");
editor.putString("name", "張三");
editor.putBoolean("isAdult", true);
editor.putFloat("height", 178.00F);
editor.putInt("age", 20);
editor.putLong("IDNum", 123456789000L);
editor.putStringSet("user", userInfo);
- 呼叫 SharedPreferences.Editor 物件的 apply() 方法或者 commit() 方法提交剛剛新增的資料:
//兩種提交方式都可以,任選其一即可
editor.apply();
editor.commit();
至此,利用 SharedPreferences 儲存資料的方法就介紹完了,下面是完整例項:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sp = getSharedPreferences("user_info", MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
Set<String> userInfo = new HashSet<>();
userInfo.add("張三");
userInfo.add("20");
editor.putString("name", "張三");
editor.putBoolean("isAdult", true);
editor.putFloat("height", 178.00F);
editor.putInt("age", 20);
editor.putLong("IDNum", 123456789000L);
editor.putStringSet("userInfo", userInfo);
editor.apply();
}
}
執行程式以後,資料就已經儲存成功了,眼見為實,在 Android Studio 中開啟 Device File Explorer ,進入 “\data\data\應用程式包名\shared_prefs\” 目錄下,結果如下:
(二)SharedPreferences 取資料
- 獲取 SharedPreferences 物件。利用 SharedPreferences 存資料時已經介紹過了獲取 SharedPreferences 物件的方法,這裡不再贅述,直接看程式碼:
/**
* 引數一:SharedPreferences檔名,必須和存資料時的檔名一致,存什麼就取什麼
* 引數二:操作模式
*/
SharedPreferences sp = getSharedPreferences("user_info", MODE_PRIVATE);
- 呼叫 SharedPreferences 物件的 getXXX() 方法,根據存資料時約定的 key 值獲取對應的資料:
/**
* SharedPreferences物件的.getXXX()方法接收兩個引數,該方法有返回值,返回key對應的value
* 引數一:儲存資料時使用的key
* 引數二:預設值,如果取值失敗則返回預設值
*/
String name = sp.getString("name", "");
boolean isAdult = sp.getBoolean("isAdult", false);
float height = sp.getFloat("height", 0F);
int age = sp.getInt("age", 0);
long IDNum = sp.getLong("IDNum", 0L);
HashSet<String> userInfo = (HashSet<String>) sp.getStringSet("userInfo", new HashSet<String>());
至此,利用 SharedPreferences 取出資料的方法就介紹完了,下面是完整例項:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sp = getSharedPreferences("user_info", MODE_PRIVATE);
String name = sp.getString("name", "");
boolean isAdult = sp.getBoolean("isAdult", false);
float height = sp.getFloat("height", 0F);
int age = sp.getInt("age", 0);
long IDNum = sp.getLong("IDNum", 0L);
HashSet<String> userInfo = (HashSet<String>) sp.getStringSet("userInfo", new HashSet<String>());
Log.d("MyLog", "姓名:" + name);
Log.d("MyLog", "是否成年:" + isAdult);
Log.d("MyLog", "身高:" + height);
Log.d("MyLog", "年齡:" + age);
Log.d("MyLog", "身份證號碼:" + IDNum);
Log.d("MyLog", "使用者資訊:" + userInfo.toString());
}
}
執行程式後,Logcat 列印的日誌結果如下:
三、apply 與 commit 的區別
- commit
/**
* Commit your preferences changes back from this Editor to the
* {@link SharedPreferences} object it is editing. This atomically
* performs the requested modifications, replacing whatever is currently
* in the SharedPreferences.
*
* <p>Note that when two editors are modifying preferences at the same
* time, the last one to call commit wins.
*
* <p>If you don't care about the return value and you're
* using this from your application's main thread, consider
* using {@link #apply} instead.
*
* @return Returns true if the new values were successfully written
* to persistent storage.
*/
boolean commit();
如上是 Editor.commit 方法的原始碼,英文好一點的童鞋能從原始碼註釋中瞭解不少東西,英語差點的童鞋不要著急,這裡我提取出原始碼註釋中的一些關鍵資訊,如下:
- commit 方法用於將需要儲存的資料通過 Editor 提交併儲存到 SharedPreferences 物件中;
- commit 提交過程屬於原子操作,也就是該提交過程不可中斷,要麼全部提交成功,要麼全部提交失敗,不會出現只儲存了其中一部分資料的情況;
- 同一個 SharedPreferences 物件,多次呼叫 commit 方法,最後一次的呼叫會覆蓋掉前面提交的資料,也就是當出現多次 commit 時,以最後一次 commit 提交的資料為準;
- commit 方法有返回值( boolean 型別),意思是如果本次寫入資料成功,返回 true,否則返回 false 。
- 如果不關心返回值(不關心資料是否寫入成功),推薦使用 apply 方法提交資料。
- apply
/**
* Commit your preferences changes back from this Editor to the
* {@link SharedPreferences} object it is editing. This atomically
* performs the requested modifications, replacing whatever is currently
* in the SharedPreferences.
*
* <p>Note that when two editors are modifying preferences at the same
* time, the last one to call apply wins.
*
* <p>Unlike {@link #commit}, which writes its preferences out
* to persistent storage synchronously, {@link #apply}
* commits its changes to the in-memory
* {@link SharedPreferences} immediately but starts an
* asynchronous commit to disk and you won't be notified of
* any failures. If another editor on this
* {@link SharedPreferences} does a regular {@link #commit}
* while a {@link #apply} is still outstanding, the
* {@link #commit} will block until all async commits are
* completed as well as the commit itself.
*
* <p>As {@link SharedPreferences} instances are singletons within
* a process, it's safe to replace any instance of {@link #commit} with
* {@link #apply} if you were already ignoring the return value.
*
* <p>You don't need to worry about Android component
* lifecycles and their interaction with <code>apply()</code>
* writing to disk. The framework makes sure in-flight disk
* writes from <code>apply()</code> complete before switching
* states.
*
* <p class='note'>The SharedPreferences.Editor interface
* isn't expected to be implemented directly. However, if you
* previously did implement it and are now getting errors
* about missing <code>apply()</code>, you can simply call
* {@link #commit} from <code>apply()</code>.
*/
void apply();
如上是 Editor.apply 方法的原始碼,這裡,我照例提取出該方法的原始碼註釋中的關鍵資訊,如下:
- 跟 commit 方法一樣,apply 方法用於將需要儲存的資料通過 Editor 提交併儲存到 SharedPreferences 物件中;
- 跟 commit 方法一樣,同一個 SharedPreferences 物件,多次呼叫 apply 方法,最後一次的呼叫會覆蓋掉前面提交的資料,也就是當出現多次 apply 時,以最後一次 apply 提交的資料為準;
相關文章
- 傻傻分不清楚的kubernetes證書
- Token ,Cookie、Session傻傻分不清楚?CookieSession
- Shell中傻傻分不清楚的TOP3
- 還傻傻分不清楚equals和==的區別嗎?看完就明白了
- Go語言切片一網打盡,別和Java語法傻傻分不清楚GoJava
- set,env,export,source,exec傻傻分不清楚?Export
- MVP、原型、概念驗證,傻傻分不清楚?MVP原型
- 依賴倒置、依賴注入和控制反轉傻傻分不清楚?依賴注入
- 2021年了,`IEnumerator`、`IEnumerable`還傻傻分不清楚?
- 寫了這麼多年 CSS,initial 和 inherit 以及 unset 和 revert 還傻傻分不清楚?CSS
- 終於不再對transition和animation,傻傻分不清楚了 --vue中使用transition和animationVue
- 懶載入、預載入、with()、load() 傻傻分不清楚?
- 快速掌握javascript的apply()和call()方法JavaScriptAPP
- 老徐和阿珍的故事:強引用、軟引用、弱引用、虛引用,傻傻分不清楚
- JS中的call()方法和apply()方法用法總結JSAPP
- 都2024年了你還傻傻分不清楚“編譯時”和“執行時”嗎?編譯
- 控制反轉,依賴注入,依賴倒置傻傻分不清楚?依賴注入
- 【死磕NIO】— 阻塞、非阻塞、同步、非同步,傻傻分不清楚非同步
- URL URI傻傻分不清楚,dart告訴你該怎麼用Dart
- 併發、並行傻傻分不清楚?執行緒的一生都經歷些什麼?並行執行緒
- python中的一個現象,db.commit和db.commit()PythonMIT
- Angular的scope. apply和CRM WebClient UI的modify方法AngularAPPWebclientUI
- 像操作Room一樣操作SharedPreferences和File檔案OOM
- 使用JS簡單實現一下apply、call和bind方法JSAPP
- js中call,apply和bind方法的區別和使用場景JSAPP
- Docker映象提交命令commit的工作原理和使用方法DockerMIT
- 老徐和阿珍的故事:快取穿透、快取擊穿、快取雪崩、快取熱點,傻傻分不清楚快取穿透
- Reflect.apply() 方法APP
- 快取穿透、擊穿、雪崩什麼的傻傻分不清楚?看了這篇文後,我明白了快取穿透
- JavaScript中的call()和apply()JavaScriptAPP
- Proxy handler.apply() 方法APP
- JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文帶你釐清箇中曲直,給你個選擇SpringDataJPA的理由!JDBCORMSpring
- 理解JS中的call、apply、bind方法(********************************************************JSAPP
- this, call, apply 和 bindAPP
- 詳解 JavaScript的 call() 和 apply()JavaScriptAPP
- call,apply和bind的區別APP
- JavaScript中call,apply,bind方法的總結。JavaScriptAPP
- Java SPI 和 API,傻傻分不清?JavaAPI