Android SharedPreferences總結及優化

一、SharedPreferences簡介


? ? ? ?Android 中的 SharedPreferences(后續簡稱SP)是輕量級的數據存儲方式,能夠保存簡單的數據類型,比如 String、int、boolean 值等。應用場合主要是數據比較少的配置信息。其內部是以 XML 結構保存在 /data/data/包名/shared_prefs 文件夾下,數據以鍵值對的形式保存。

? ? ? ?使用Preference來存取數據,用到了SP接口和SP的一個內部接口SharedPreferences.Editor,這兩個接口在android.content包中。

? ? ? ?調用Context.getSharedPreferences(String name,int mode)方法得到SP接口。該方法的第一個參數是文件名稱,第二個參數是操作模式。操作模式有三種:MODE_PRIVATE(私有)、MODE_WORLD_READABLE(可讀)、MODE_WORLD_WRITEABLE(可寫)。

? ? ? ?SP提供了獲得數據的方法,如getString(String key,String defValue)、getInt(String key,int defValue)等。調用SP的edit()方法返回SharedPreferences.Editor內部接口,該接口中提供了保存數據的方法,如putString(String key,String value),putInt(String key,int value)等,調用該接口的commit()方法可以將數據進行保存。


二、SP性能優化點


SP性能變差的原因有很多。

1、原生API的限制

(1)IO瓶頸
IO瓶頸造成SP性能差是最大的原因,解決了IO瓶頸,80%的性能問題就解決了。
SP的IO瓶頸包括讀取數據到內存與數據寫入磁盤兩部分。

讀取數據到內存有兩個場景會觸發:
  1. SP文件沒有被加載到內存時,調用getSharedPreferences方法會初始化文件并讀入內存。
  2. 版本低于android_H或使用了MULTI_PROCESS標志時,每次調用getSharedPreferences方法時都會讀入。
我們可以優化的便是(2)了。每次加載數據到內存太過影響效率。
H以下版本留存率已經很低了,基本可以忽略。
對于MULTI_PROCESS,可以采用ContentProvider等其他方式,效率更好,而且可避免SP數據丟失的情況。

數據寫入磁盤也有兩個場景會觸發:
  1. Editor的commit方法,每次執行時同步寫入磁盤。
  2. Editor的apply方法,每次執行時在單線程池中加入寫入磁盤Task,異步寫入。
commit和apply的方法區別在于同步寫入和異步寫入,以及是否需要返回值。
在不需要返回值的情況下,使用apply方法可以極大的提高性能。
同時,多個寫入操作可以合并為一個commit/apply,將多個寫入操作合并后也能提高IO性能。

(2)鎖性能差

SP的get操作,會鎖定SharedPreferences對象,互斥其他操作。
SP的put操作,getEditor及commitToMemory會鎖定SharedPreferences對象,put操作會鎖定Editor對象,寫入磁盤更會鎖定一個寫入鎖。
由于鎖的緣故,SP操作并發時,耗時會徒增。減少鎖耗時,是另一個優化點。
由于讀寫操作的鎖均是針對SP實例對象的,將數據拆分到不同的sp文件中,便是減少鎖耗時的直接方案。
降低單文件訪問頻率,多文件均攤訪問,以減少鎖耗時。
用開發機進行了簡單的性能測試(寫入均使用apply,若使用commit則多線程耗時更高):
讀寫同一文件,10個線程每個讀寫10次數據:
耗時80-130ms
讀寫10個文件,每個文件由1個線程讀寫10次數據:
耗時30-70ms


2、對SP的不當封裝也會間接造成數據讀寫性能差。

由于我們項目采用了插件化,所以對SP的操作涉及到了跨進程訪問。
我們采用ContentProvider方案支持跨進程訪問,并對所有SP操作均套上了ContentProvider進行訪問。
隨著項目越來越龐大,通過ContentProvider訪問造成的耗時性能也成了問題。
對ContentProvider操作SP測試,耗時是直接操作SP的4倍左右。
所以,最近項目中進行了SP的處理,對于不需要跨進程的SP操作去掉了ContentProvider,盡可能減少無謂耗時。

三、SP優化的建議


1、盡量不要直接調用SharedPreferences進行讀寫操作。


若直接調用getSharedPreferences(fileName,mode).edit().putString(key,value),則對數據的操作直接耦合了fileName和key,后續想調整file和key會比較困難。
可以考慮封裝一下,譬如:
public void saveUserId(){getSharedPreferences(fileName,mode).edit().putString(“user_id”,value);
}
這樣做可以直接對數據訪問,而與fileName與key解耦,后續拆分與調整時會很方便。

2、將SP作為耗時操作對待,盡量減少無謂的調用。

譬如以下代碼,SP讀一次即可:
if(sp.getUserId()>0){int id=sp.getUserId();...
}

五、其他程序訪問本程序的配置數據方式

? ? ? ?通過SharedPreferences創建的配置文件,不需要指定路徑和文件后綴名,讀取的時候也是。通常情況下,配置只是提供給本應用程序使用的。在這里我們介紹一個小知識點,即其他程序想使用本應用程序的配置,那應該如何使用SharedPreferences呢?如下:
Context otherAppContext = createPackageContext("com.gary.appdisplaycontrol", Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = otherAppContext.getSharedPreferences("preferences",Context.MODE_WORLD_READABLE|Context.MODE_MULTI_PROCESS); 
備注:必須要添加Context.MODE_MULTI_PROCESS屬性,否則會遇到其他程序讀取數據未更新問題



本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/446970.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/446970.shtml
英文地址,請注明出處:http://en.pswp.cn/news/446970.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java基礎——深入理解ReentrantLock

一、簡介在Java中通常實現鎖有兩種方式,一種是synchronized關鍵字,另一種是Lock。二者其實并沒有什么必然聯系,但是各有各的特點,在使用中可以進行取舍的使用。二、ReentrantLock與synchronized的比較相同點: &#xf…

使用開源的openssl的md5頭文件,實現對于文件的md5代碼

需要安裝openssl的庫 sudo apt-get install opensslsudo apt-get install libssl-dev參考鏈接 代碼 #include "openssl/md5.h" #include <iostream> #include <fstream> #include <iomanip>//#define MAX_DATA_BUFF 1024; //#define MD5_LENGTH…

Android 多進程開發

前言正常情況下&#xff0c;一個apk啟動后只會運行在一個進程中&#xff0c;其進程名為AndroidManifest.xml文件中指定的應用包名&#xff0c;所有的基本組件都會在這個進程中運行。但是如果需要將某些組件&#xff08;如Service、Activity等&#xff09;運行在單獨的進程中&am…

clion中鏈接openssl庫

錯誤顯示 前提條件 apt-get install opensslapt-get install openssl-dev 解決辦法 在CMakeLists.txt文件中加入如下命令link_libraries(crypto) 參考鏈接 無法將openssl庫鏈接到CLion C 程序c - 無法將openssl庫鏈接到CLion C程序

Java中String、StringBuffer、StringBuilder三者的區別

一、簡介String、StringBuffer、StringBuilder三個類之間的區別主要是在兩個方面&#xff1a;運行速度和線程安全。二、區別1、運行速度&#xff0c;或者說是執行速度在這方面運行速度快慢為&#xff1a;StringBuilder > StringBuffer > String StringString為字符串常量…

Ubuntu環境下,使用clion編譯器,使用開源opensll的對稱AES算法對于文件進行加密,C++代碼

前提準備條件 需要安裝openssl需要安裝openssl-dev需要配置CMakeLists.txt文件集體內容可以參考我提供的相關參考鏈接 AES_file.h #include <openssl/aes.h> #include <iostream> #include <fstream> #include <cstring>#define RELEASE_ARRAY(P) if…

Java提高篇 —— Java關鍵字之static的四種用法

一、前言 在java的關鍵字中&#xff0c;static和final是兩個我們必須掌握的關鍵字。不同于其他關鍵字&#xff0c;他們都有多種用法&#xff0c;而且在一定環境下使用&#xff0c;可以提高程序的運行性能&#xff0c;優化程序的結構。下面我們先來了解一下static關鍵字及其用法…

C++ 使用move來刪除用戶指定的文件

代碼 #include <iostream>bool remove_file(std::string path){if (remove(path.c_str())0){std::cout << "success!" << std::endl;}else{std::cout << "False!" << std::endl;} } int main() {std::string path "/…

Java提高篇 —— Java關鍵字之final的幾種用法

一、前言 在java的關鍵字中&#xff0c;static和final是兩個我們必須掌握的關鍵字。不同于其他關鍵字&#xff0c;他們都有多種用法&#xff0c;而且在一定環境下使用&#xff0c;可以提高程序的運行性能&#xff0c;優化程序的結構。下面我們來了解一下final關鍵字及其用法。 …

使用C++的方式實現AES算法

aes_file.h #include <iostream> #include <fstream> #include <bitset> #include <string> using namespace std; typedef bitset<8> byte; typedef bitset<32> word;const int Nr 10; // AES-128需要 10 輪加密 const int Nk 4; /…

Java提高篇 —— Java三大特性之封裝

一、封裝 封裝從字面上來理解就是包裝的意思&#xff0c;專業點就是信息隱藏&#xff0c;是指利用抽象數據類型將數據和基于數據的操作封裝在一起&#xff0c;使其構成一個不可分割的獨立實體&#xff0c;數據被保護在抽象數據類型的內部&#xff0c;盡可能地隱藏內部的細節&am…

sqlite3的backup和restore函數的使用

參考代碼 第一段這個親測可以使用 #include <sqlite3.h> #include <iostream> /* ** Perform an online backup of database pDb to the database file named ** by zFilename. This function copies 5 database pages from pDb to ** zFilename, then unlocks pD…

Java提高篇 —— Java三大特性之繼承

一、前言 在《Think in java》中有這樣一句話&#xff1a;復用代碼是Java眾多引人注目的功能之一。但要想成為極具革命性的語言&#xff0c;僅僅能夠復制代碼并對加以改變是不夠的&#xff0c;它還必須能夠做更多的事情。在這句話中最引人注目的是“復用代碼”,盡可能的復用代碼…

Java提高篇 —— Java三大特性之多態

一、前言 面向對象編程有三大特性&#xff1a;封裝、繼承、多態。 封裝&#xff1a;隱藏了類的內部實現機制&#xff0c;可以在不影響使用的情況下改變類的內部結構&#xff0c;同時也保護了數據。對外界而已它的內部細節是隱藏的&#xff0c;暴露給外界的只是它的訪問方法。 繼…

光盤刻錄制作Ubuntu等操作系統的啟動盤

前提條件 軟媒刻錄 空白光盤&#xff08;至少4.7G&#xff09;電腦&#xff08;最好使用外置的光驅&#xff09;系統鏡像&#xff08;ISO格式&#xff09; 具體操作 打開軟媒魔方選擇光盤刻錄按照標紅的進行選擇選擇鏡像->選擇或者拖拽都可以選擇刻錄機->如果使用外部刻…

Java提高篇 —— 抽象類與接口

一、前言 接口和內部類為我們提供了一種將接口與實現分離的更加結構化的方法。 抽象類與接口是java語言中對抽象概念進行定義的兩種機制&#xff0c;正是由于他們的存在才賦予java強大的面向對象的能力。他們兩者之間對抽象概念的支持有很大的相似&#xff0c;甚至可以互換&…

C++ const相關內容學習

const 作用 修飾變量&#xff0c;說明變量不可以被修改修飾指針&#xff0c;分為指向常量的指針&#xff08;pointer to const&#xff09;和自身是常量的指針&#xff08;常量指針&#xff0c;const pointer&#xff09;修飾引用&#xff0c;指向常量的引用&#xff08;refe…

Java提高篇 —— Java淺拷貝和深拷貝

一、前言 我們知道在Java中存在這個接口Cloneable&#xff0c;實現該接口的類都會具備被拷貝的能力&#xff0c;同時拷貝是在內存中進行&#xff0c;在性能方面比我們直接通過new生成對象來的快&#xff0c;特別是在大對象的生成上&#xff0c;使得性能的提升非常明顯。然而我們…

openssl里面AES算法主要函數的參數的介紹

注意事項 使用API的時候&#xff0c;需要特別小心數據長度&#xff0c;一般沒有指定長度的參數&#xff0c;默認都是16&#xff08;AES_BLOCK_SIZE&#xff09;個字節。輸出數據的長度一般都是16字節的倍數&#xff0c;否則會出現數組越界訪問。以下API中&#xff0c;encrypt表…

Java提高篇 —— Java內部類詳解

一、簡介 內部類是一個非常有用的特性但又比較難理解使用的特性。 內部類我們從外面看是非常容易理解的&#xff0c;無非就是在一個類的內部在定義一個類。 public class OuterClass {private String name ;private int age;public String getName() {return name;}public voi…