摘要:概述可以通過獲取到,它是一個接口,實現在源碼也僅僅只有行,相對于龐大的源碼,小很多。但是你真的了解它嗎問題不同的里面獲取的相同嗎支持并發(fā)嗎直接保存了嗎針對上面的問題,我們一點點來分析。但是僅僅是保存到了中,正真的是要在或之后。
概述說在前面:SharedPreferences是Android中幾種重要的存儲數據的方式,Android開發(fā)不會沒有人從來沒有使用過,但是卻很好人會關注它是怎么實現的,確實SharedPreferences實現起來比較簡單,本質是基于文件存儲,格式是XML形勢的,本篇文章并沒有太深的技術,但絕對是不可缺少的知識。
SharedPreferences可以通過Context獲取到,它是一個接口,實現在frameworksbasecorejavaandroidappSharedPreferencesImpl.java
源碼也僅僅只有630行,相對于龐大的Android源碼,小很多。但是你真的了解它嗎?
問題1、不同的Activity里面Context.getSharedPreferences()獲取的SharedPreferences相同嗎?
2、支持并發(fā)嗎?
3、SharedPreferences.putXXX()直接保存了嗎?
......
針對上面的問題,我們一點點來分析。
獲得SharedPreferences我們獲得SharedPreferences是通過Context.getSharedPreferences(),源碼如下:
@Override public SharedPreferences getSharedPreferences(String name, int mode) { SharedPreferencesImpl sp; synchronized (ContextImpl.class) { // 靜態(tài)的 全局唯一,緩存得到的SharedPreferences,key是app包名 if (sSharedPrefs == null) { sSharedPrefs = new ArrayMap創(chuàng)建SharedPreferences>(); } // 通過每一個app的包名緩存不同的SharedPreferences,key是文件名 // 這里就明白前面提到的第一個問題了,一個文件對應一個SharedPreferences final String packageName = getPackageName(); ArrayMap packagePrefs = sSharedPrefs.get(packageName); if (packagePrefs == null) { packagePrefs = new ArrayMap (); sSharedPrefs.put(packageName, packagePrefs); } // 略... // 如果以創(chuàng)建過,直接從緩存中獲取返回 sp = packagePrefs.get(name); if (sp == null) { // 如果沒有創(chuàng)建一個 文件名為data/data/packege/shared_prefs/xxx.xml File prefsFile = getSharedPrefsFile(name); sp = new SharedPreferencesImpl(prefsFile, mode); // 創(chuàng)建實例對象 packagePrefs.put(name, sp); // 放到緩存中 return sp; } } // 略... return sp; }
SharedPreferences的創(chuàng)建很簡單,我們先看看構造方法:
// 僅有一個 SharedPreferencesImpl(File file, int mode) { mFile = file; mBackupFile = makeBackupFile(file); // 創(chuàng)建備份 mMode = mode; mLoaded = false; mMap = null; // 存放鍵值對的map startLoadFromDisk(); // 從本地load出來 }
從構造函數我們不難看出,SharedPreferences實際是以Map(HashMap)存儲數據,創(chuàng)建的時候就從本地文件中讀取數據到內存中,所以,不能存儲太多的數據 ,否則內存會爆掉的哦。
讀取本地文件中的數據當實例化的時候就會觸發(fā),一個讀取本地已存儲的數據,
private void loadFromDiskLocked() { // 讀取過就不在讀取 if (mLoaded) { return; } //... Map map = null; StructStat stat = null; try { // 存儲文件狀態(tài) stat = Os.stat(mFile.getPath()); if (mFile.canRead()) { BufferedInputStream str = null; try { str = new BufferedInputStream( new FileInputStream(mFile), 16*1024); // 格式為xml,解析xml得到map map = XmlUtils.readMapXml(str); } catch (XmlPullParserException e) { Log.w(TAG, "getSharedPreferences", e); } catch (FileNotFoundException e) { Log.w(TAG, "getSharedPreferences", e); } catch (IOException e) { Log.w(TAG, "getSharedPreferences", e); } finally { IoUtils.closeQuietly(str); } } } catch (ErrnoException e) { } // 加載過后更改狀態(tài),如果沒有創(chuàng)建一個HashMap mLoaded = true; if (map != null) { mMap = map; mStatTimestamp = stat.st_mtime; mStatSize = stat.st_size; } else { mMap = new HashMap獲得存儲的數據(); } notifyAll(); }
得到數據通常是getXXX(),實際很簡單,就是存map中取數據。
// 已getString()為例,其他一樣 @Nullable public String getString(String key, @Nullable String defValue) { // 同步哦 synchronized (this) { // 確保,已從文件中讀取過數據 awaitLoadedLocked(); // 從map中的得到數據 String v = (String)mMap.get(key); return v != null ? v : defValue; } }保存數據
大家都知道保存數據是通過Editor來存儲的,事實上也確實是這樣的。但是putXXX()僅僅是保存到了map中,正真的是要在commit()或apply()之后。
public Editor putString(String key, @Nullable String value) { // 同步哦 synchronized (this) { mModified.put(key, value); return this; } }
1、
public boolean commit() { MemoryCommitResult mcr = commitToMemory(); // 寫數據 SharedPreferencesImpl.this.enqueueDiskWrite( mcr, null /* sync write on this thread okay */); try { mcr.writtenToDiskLatch.await(); } catch (InterruptedException e) { return false; } notifyListeners(mcr); return mcr.writeToDiskResult; }
2、
private void enqueueDiskWrite(final MemoryCommitResult mcr, final Runnable postWriteRunnable) { final Runnable writeToDiskRunnable = new Runnable() { public void run() { synchronized (mWritingToDiskLock) { // 往文件中寫入數據 writeToFile(mcr); } synchronized (SharedPreferencesImpl.this) { mDiskWritesInFlight--; } if (postWriteRunnable != null) { postWriteRunnable.run(); } } }; // ... QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable); }
3、
// Note: must hold mWritingToDiskLock private void writeToFile(MemoryCommitResult mcr) { // ... try { FileOutputStream str = createFileOutputStream(mFile); if (str == null) { mcr.setDiskWriteResult(false); return; } // 寫入到文件中 XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str); FileUtils.sync(str); str.close(); ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0); try { // 更新文件的狀態(tài) final StructStat stat = Os.stat(mFile.getPath()); synchronized (this) { mStatTimestamp = stat.st_mtime; mStatSize = stat.st_size; } } catch (ErrnoException e) { // Do nothing } // Writing was successful, delete the backup file if there is one. mBackupFile.delete(); mcr.setDiskWriteResult(true); return; } catch (XmlPullParserException e) { Log.w(TAG, "writeToFile: Got exception:", e); } catch (IOException e) { Log.w(TAG, "writeToFile: Got exception:", e); } // Clean up an unsuccessfully written file if (mFile.exists()) { if (!mFile.delete()) { Log.e(TAG, "Couldn"t clean up partially-written file " + mFile); } } mcr.setDiskWriteResult(false); }總結
1、SharedPreferences有緩存
2、數據是通過map來快速訪問,所以不用擔心文件IO耗時
3、支持多線程并發(fā)
4、本質是基于文件xml的形式
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66790.html
摘要:真正要做高性能的系統,不僅需要在數據結構與算法層面深入,更要從硬件操作系統文件系統底層原理等多個領域做更多的研究例如阿里云自研的系統使用了裸盤技術。 《CDN之我見》共由三個篇章組成,分為原理篇、詳解篇和隕坑篇。本篇章適合那些從未接觸過、或僅了解一些 CDN 專業(yè)術語,想深入了解和感受 CDN 究竟是什么的同學。本次由白金老師繼續(xù)為大家分享《CDN之我見》系列二,主要講解緩存是什么、工...
摘要:真正要做高性能的系統,不僅需要在數據結構與算法層面深入,更要從硬件操作系統文件系統底層原理等多個領域做更多的研究例如阿里云自研的系統使用了裸盤技術。 《CDN之我見》共由三個篇章組成,分為原理篇、詳解篇和隕坑篇。本篇章適合那些從未接觸過、或僅了解一些 CDN 專業(yè)術語,想深入了解和感受 CDN 究竟是什么的同學。本次由白金老師繼續(xù)為大家分享《CDN之我見》系列二,主要講解緩存是什么、工...
摘要:在我們寫項目代碼的過程中,要經常請求接口數據,在某些異步請求數據之后,將得到的值進行處理。 在我們寫項目代碼的過程中,要經常請求接口數據,在某些異步請求數據之后,將得到的值進行處理。通俗的一句話就是,我要把這個值放到另一個函數中,按行數順序處理,即同步的概念! 例子:第一步,涉及異步函數 假設我有一個函數abc, function abc(){ //異步方法,請求數據得到re...
摘要:通過我們可以更輕松地入門,更簡單的使用的框架。團隊為了擺脫框架中各類繁復紛雜的配置,使用約定優(yōu)于配置的思想,在基礎上整合了大量常用的第三方庫的開發(fā)框架。這里還要說的一點,的出現并不是單純的為了簡化開發(fā),更是為做鋪墊。 說完了Spring 我們來聊聊Spring的進階版Spring Boot,如果你還不知道Spring Boot,那希望這篇文章能夠為你指明方向。 Spring Boot ...
閱讀 1652·2021-08-13 15:03
閱讀 2082·2019-08-30 15:54
閱讀 3544·2019-08-26 10:30
閱讀 1020·2019-08-26 10:22
閱讀 2746·2019-08-23 14:42
閱讀 1809·2019-08-22 11:16
閱讀 1038·2019-08-21 18:33
閱讀 3159·2019-08-21 17:28