自我提升(基礎技術篇)——Android本地數據存儲

前言,好吧,這部分,沒那么多要說的,其實,就是運用。主要是,畢竟客戶端,存儲并非重點。不過,還是要了解和學習的

先來補充一點基礎嘗試吧:(免得以后,聽到別人聊起,自己一臉蒙蔽)

ADT:Android 開發工具

API:應用程序編程接口

IDE:集成開發環境

JDK:Java 開發工具包

JSON:JavaScript 對象表示法

SDK:軟件開發工具包

SQL:結構化查詢語言

UI:用戶界面

XML:可擴展標記語言


ok,回到正題,本文,主要講的是數據存儲,主要是以系統講解為主,因為,如果只是運用的話,大可百度,一大堆文章可以看,一大堆框架可以用。順便說一下:我寫的自我提升系列,都是屬于系統的介紹某個東西,深入介紹會在后面的其他系列中寫。

原本是打算從一個例子出發的,不過,后來想了一想,這個問題,還是留給讀者自己去想吧,不然,讀者都不會思考了。下面就簡單介紹一下常用的存儲方式吧,這里,將會單純的從技術層面去介紹。

SharedPreferences

這玩意,算是這些存儲中最簡單的方式了吧,不過,還是有一些細節需要知道,不然,也容易出錯的

簡單介紹

SharePreferences是用來存儲一些簡單配置信息的一種機制,使用Map數據結構來存儲數據,以鍵值對的方式存儲,采用了XML格式將數據存儲到設備中,只能在同一個包內使用,不能在不同的包之間使用,其實也就是說只能在創建它的應用中使用,其他應用無法使用。(這里順便說一下,在libary引入的情況下,也是可以使用的,不過,順序是,引用者和自己可以使用,其他不可以使用)

創建的存儲文件保存在/data/data//shares_prefs文件夾下。

創建文件的模式

Context.MODE_PRIVATE(個人建議,用這種模式)

默認操作模式,表示xml存儲文件是私有的,只能在創建文件的應用中訪問(如果其他應用和創建該文件的應用具有相同的uid,也可以直接訪問)。

Context.MODE_WORLD_WREADABLE(不建議使用)

開放讀模式,表示允許其他應用進程具備對該文件的讀權限。官方文檔不建議使用該模式,因為這為導致嚴重的安全漏洞。

Context.MODE_WORLD_WRITABLE(不建議使用)

開放寫模式,表示允許其他應用進程具備堆該文件的寫權限,原因同上一條

Context.MODE_APPEND(個人不建議使用,嫌麻煩

追加模式,和openFileOutput一起使用。該模式下如果文件存在,就往文件末尾進行追加,否則創建新文件。

簡單使用

通過Context.getSharedPreferences方法獲取SharedPreferences對象,參數分別為存儲的文件名和存儲模式。

?獲取SharedPreferences對象

SharedPreferences?sp?=?getSharedPreferences(DATABASE,?Activity.MODE_PRIVATE);

?獲取Editor對象

Editor?editor?=?sp.edit();

插入數據

調用Editor.putxxxx方法,兩個參數分別為鍵和值。(注意,這里put要指明類型,比如putSting(?,?))

獲取數據:

調用Editor.getxxxx方法,兩個參數分別為鍵和不存在指定鍵時的默認值。

刪除數據:

調用Editor.remove方法,參數為指定的鍵。

清空所有數據:

調用Editor.clear方法

上述所有方法調用都要執行Editor.commit方法來提交,例子:editor.putString("hello",hello).commit.

個人封裝方法(由于,常規的寫法,個人覺得,要去寫key,后面用的時候,也要寫key,感覺很煩,所以就把key集成在了名字里面)


我的包結構吧,名字應該很形象吧。多的就不說,繼續往下看。

這個BaseSp的左右,就是初始化sp,我這里,舉例,就只寫了String的api。其他的是一個意思的。

這里的BasePrefItem是父類item,這其中,簡單的用到了泛型,因為,我并不知道我要存什么類型的key value。

這里是具體的item,當然,是以String為例的,多的不想解釋,代碼很明顯了。

這里是具體的sp了,繼承basesp,寫入文件名,然后,就是創建各個類型的item,一次寫好,一輩子不愁的思想。


使用,簡單吧,經過我前面的封裝,使用,永遠是一句話,而且,看名字就明了了吧,不用再去找一個類,專門放各種常量了吧,這種寫法,唯一比較大的類,就是上面的AppSP這個類了,不過,通常,我會根據業務,或者數據模型,去寫不同的實現類 SP。

需要注意一點:SP是線程不安全的,所以,在同步,多線程里面,最好不要用SP。

SQLite數據庫

這玩意,說實話,我在項目中,用得比較少,講真,在這個時代,網絡才是王道(客戶端而言)。不過,也得學,不是

SQLite 介紹

SQLite 一個非常流行的嵌入式數據庫,它支持 SQL 語言,并且只利用很少的內存就有很好的性能。此外它還是開源的,任何人都可以使用它。許多開源項目((Mozilla, PHP, Python)都使用了 SQLite.

SQLite 由以下幾個組件組成:SQL 編譯器、內核、后端以及附件。SQLite 通過利用虛擬機和虛擬數據庫引擎(VDBE),使調試、修改和擴展 SQLite 的內核變得更加方便。為了解釋,在網上找的簡易版示意圖。


SQLite 基本上符合 SQL-92 標準,和其他的主要 SQL 數據庫沒什么區別。它的優點就是高效,Android 運行時環境包含了完整的 SQLite。

SQLite 和其他數據庫最大的不同就是對數據類型的支持,創建一個表時,可以在 CREATE TABLE 語句中指定某列的數據類型,但是你可以把任何數據類型放入任何列中。當某個值插入數據庫時,SQLite 將檢查它的類型。如果該類型與關聯的列不匹配,則 SQLite 會嘗試將該值轉換成該列的類型。如果不能轉換,則該值將作為其本身具有的類型存儲。比如可以把一個字符串(String)放入 INTEGER 列。SQLite 稱這為“弱類型”(manifest typing.)。

此外,SQLite 不支持一些標準的 SQL 功能,特別是外鍵約束(FOREIGN KEY constrains),嵌套 transcaction 和 RIGHT OUTER JOIN 和 FULL OUTER JOIN, 還有一些 ALTER TABLE 功能。(這其實也是sqlite的雞肋之處)

除了上述功能外,SQLite 是一個完整的 SQL 系統,擁有完整的觸發器,交易等等。(小但強大)

Android 集成了 SQLite 數據庫

Android 在運行時(run-time)集成了 SQLite,所以每個 Android 應用程序都可以使用 SQLite 數據庫。對于熟悉 SQL 的開發人員來時,在 Android 開發中使用 SQLite 相當簡單。但是,由于 JDBC 會消耗太多的系統資源,所以 JDBC 對于手機這種內存受限設備來說并不合適。因此,Android 提供了一些新的 API 來使用 SQLite 數據庫,Android 開發中,我們需要學使用這些 API。

數據庫存儲在 data/< 項目文件夾 >/databases/ 下。

Android 開發中使用 SQLite 數據庫

關于這個數據庫的問題,個人而言實在是沒多少可以說的,畢竟對sqlite的使用比較少,不想誤導大家,所有,就請大家自行百度,sqlite語法了吧。

不過,先提出幾個理念:數據庫的一行,相當于,java中的一個對象。所以,在Android中,使用sqlite,一般都是,把對象存為一個表,這個表中只有一行最新的唯一數據,而使用的時候,通常也是取出一行,賦值給一個對象,然后,操作對象。

這一部分,算是寫得有點水了吧,不過,沒法。見諒了。順帶說一句,本來,是想好好說一下關于數據庫更新的問題,不過發現,數據更新是個麻煩事兒,特別是涉及到跨版本升級的問題。這里,就不多說了,只是提一句。

Internal Storage 和 External Storage

簡單介紹(Internal Storage 其實就是我們說的私有數據,External Storage簡單說,就是sdcard,簡單可以這么粗暴的理解)

Internal Storage 和 External Storage 的區別

Internal storage 是屬于應用程序的,文件管理器看不見。(私有)

External storage 在文件瀏覽器里是可以看見的? /mnt 。(共有)

這兩個概念都是相對于應用來說的,應該理解為邏輯上的概念,不應理解為物理上的外部SD卡和手機或移動設備內存.。

一個應用把數據存在external storage上時,那么數據成為共有的,所有人都可見的和可用的。

存在internal storage上時,只有這個應用本身可以看到和使用。

很多沒有插SD卡的設備,系統會虛擬出一部分存儲空間用來做公共存儲(主要是音樂,文檔之類的media)。

所以:如果是私密性,安全性的文件數據,就存Internal Storage,如果是大家共用的就存External Storage(ps:在高手面前,這兩個都是可以被查看的,只是相對于軟件本身是安全的,私密的)

Internal Storage 把數據存儲在設備內部存儲器上,存儲在/data/data//files目錄下。

默認情況下在這里存儲的數據為應用程序的私有數據,其它應用程序不能訪問。

卸載應用程序后,內部存儲器的/data/data/目錄及其下子目錄和文件一同被刪除。

ok,下面再詳細,分別介紹,這二者是怎么使用的:

Internal Storage使用介紹

存數據(也可以叫寫數據,其實正規叫法是寫數據,不過,方便理解,就交存數據)

1. 調用openFileOutput(String fileName, int mode)方法,

若fileName對應的文件存在,就打開該文件,若不存在,并以mode權限創建該文件并打開,該方法

返回一個指向fileName對應文件的FileOutputStream,使用這個FileOutputStream可向文件中寫入數據。

2. 調用FileOutputStream對象的write()方法向文件中寫入數據。

3. 調用FileOutputStream對象的close()方法關閉文件寫入流。

例:向內部存儲器中寫入一個名為"abc.txt"的文件后,會在內部存儲器的/data/data//files/目錄下生成"abc.txt"文件。

1,2,3步對應上圖。login就是我們所存的文件,文件中我們存如了username和password。

取數據(也叫讀數據)

1. 調用openFileInputStream(String fileName)方法打開內部存儲器中fileName對應的文件,若該文件存在,該方法

返回一個指向fileName文件的FileInputStream對象。

2. 調用FileInputStream對象的read()方法讀取fileName文件中的內容。

3. 調用FileInputStream對象的close()方法關閉文件讀取流。


如上圖,經過讀取數據之后,會把讀出來的字符放到buffer中,然后,我們就可以從buffer中,拿出我們要的string了。

ok,內部存儲的知識,就介紹到這里,不過,這個內部存儲有一個軟肋,就是軟件被卸載,他就沒有了,這點和sp其實差不多,所以,當我們需要保存一些數據,達到,就算軟件卸載了,再安裝也能使用的效果時,就需要用到接下來要用的東西了,外部存儲。

External Storage 簡單介紹即使用

簡單介紹

它并非始終可用,因為用戶可采用 USB 存儲設備的形式裝載外部存儲,并在某些情況下會從設備中將其移除。

它是全局可讀的,因此此處保存的文件可能不受您控制地被讀取。

當用戶卸載您的應用時,保存在Environment.getExternalStoragePublicDirectory()目錄里的文件不會被刪除,保存在getExternalFilesDir()或getExternalCacheDir()目錄里的文件會被刪除

對于無需訪問限制以及您希望與其他應用共享或允許用戶使用計算機訪問的文件,外部存儲是最佳位置。

如果您的應用需要只需讀取外部存儲,需在清單文件申請android.permission.READ_EXTERNAL_STORAGE權限

如果您的應用需要寫入(隱含讀取)外部存儲,只需在清單文件申請android.permission.WRITE_EXTERNAL_STORAGE權限

通常,是兩個權限都申請

存數據:(寫入)

1? 通過Environment類的getExternalStorageState()方法來判斷手機是否有SDcard

Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)

2.獲取SD卡的目錄

File file = Environment.getExternalStorageDirectory();

3.創建文件,或者在原文件中添加數據

FileOutputStream fileW =newFileOutputStream(file.getCanonicalPath() +"/test.txt");

fileW.write(str.getBytes());

4.關流

fileW.close();


細心的同學,應該會注意到,這里的filew.close為什么不是寫在finaly里面呢?好吧,的確應該寫在finaly里面的,或許又有發現,怎么在存數據的最后沒有清空緩存呢?好吧,其實也應該那么做的,所以,最正確的寫法,應該是在寫入數據之后清空緩存,然后在finaly里面close。

那么,我為什么不這么寫呢?因為我以前就是這么寫的,但是,也沒有出錯。不過,最好還是嚴謹一點吧。

取數據:(讀出)

1.判斷sd卡是否存在,獲取sd卡目錄

2.獲取文件,判斷文件是否存在(這里其實,就是先假設文件存在,獲取文件)

3.打開文件輸入流

4.把讀出來的數據,添加到buffer

5.遍歷buffer,轉換成string

ok,外部存儲,基本就是這樣了。

小結

這一篇文章寫的時間,相對比較長,主要寫得合適,不能太復雜,也不能太簡單。其實,本問中,對于數據的地方,真心想寫,但也不敢寫,這部分,說簡單,也簡單,說難也難。所以,干脆就簡單介紹一下。本文主要介紹了Android本地存儲的一些基本東西,不過,說實在的,就app而言的話,這部分,個人覺得不是特別重要(但是,還是重要的,只是程度沒有網絡,線程,效果那些重要,當然,難度,也相對較低),但是,如果走比較深入的話,那就另當別論了。比如,數據庫的版本更新,數據結構的設計等等。不然怎么有專門的數據庫架構師

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,710評論 25 708
  • 之前閑著無聊,研究了下 Android 存儲方面的知識,順便翻譯了下官方文檔(雖然有已經被翻譯過...)。這里就算...
    koguma閱讀 1,000評論 0 3
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,818評論 18 139
  • 我又再次見到了那飄散著的一片片落葉。 見到落葉并不稀奇,但是這是在春天,四月的春天!春天見得最多的應是傲然怒...
    Luckever閱讀 490評論 0 0
  • 《夜的孩子》 井中的月亮披上紅妝 盲人坐在樹樁上低唱 我渴望一場海潮到來 載著一船星星航行在云天上 有一個叫孤獨的...
    鄭凌霄閱讀 334評論 5 2