一、Android數據的存儲方式:
Android系統一共提供了四種數據存儲方式。分別是:SharePreference、SQLite、Content Provider和File;此外還有一種網絡存儲。由於Android系統中,數據基本都是私有的,都是存放於“data/data/程序包名”目錄下,所以要實現數據共享,正確方式是使用Content Provider。
在Android中,可以使用幾種方式實現數據持久化:
- Shared Preferences:除SQLite數據庫外,另一種常用的數據存儲方式。共享參數形式,一種以Key-Value的鍵值對形式保存數據的方式,其本質就是一個xml文件。Android內置的,一般應用的配置信息,推薦使用此種方式保存。
- Internal Storage:使用Android設備自帶的內存存儲數據。
- External Storage:使用外部存儲設備存儲數據,一般是指Sdcard。
- SQLite Databases:以SQLite數據庫存儲結構化的數據。SQLite是一個輕量級的數據庫,支持基本SQL語法,是常被采用的一種數據存儲方式。Android為此數據庫提供了一個名為SQLiteDatabase的類,封裝了一些操作數據庫的API。
- Network Connection:使用基於網絡的服務獲取數據。
二、Android的文件系統:
1、Android系統文件目錄:
2、Android的應用數據存儲機制:
在Android中,第三方應用及其數據,都存放在data目錄下。其中,應用安裝包會被存放到/data/app/目錄下,每個安裝包的文件名都形如:應用包名.apk,以避免重復。比如包名為com.test.sample的應用,其應用數據的目錄為/data/data/com.test.sample/。對應的數據庫文件存儲在/data/data/com.test.sample/database/目錄下,設置文件存儲在/data/data/com.test.sample/shared_prefs/,自定義的應用數據文件存儲在目錄/data/data/com.test.sample/files/下,等等。
不僅如此,Android還會為每個應用創建一個賬號,只有通過本應用的賬號才有權限去運行該應用的安裝包文件,讀寫應用數據目錄下的文件(當然root權限除外),從而保證了該應用數據不會再被其他應用獲取或破壞。
3、Android的文件操作:
從應用數據目錄下可以看出,數據文件可以分成兩類,一類是放置在擴展存儲器中的文件,即/sdcard/目錄下的文件,它們可以被各個應用共享;而另一類則是放在該應用數據目錄下文件,它們僅能被各個應用獨享,不能被其他應用讀寫。
三、SharedPreferences:
在所有應用程序中,都必然涉及數據的交互。有些時候,應用程序有少量的數據需要保存,並且這些數據的格式很簡單。比如:軟件設置、用戶賬戶設置,用戶習慣設置等,這個時候就可以用到SharedPreferences。
其實,SharedPreferences使用xml格式為Android應用提供一種永久的數據存貯方式,並且是使用鍵值對的方式來存儲數據的。對於一個Android應用,它存貯在文件系統的/data/data/your_app_package_name/shared_prefs/目錄下,可以被處在同一個應用中的所有Activity 訪問。Android 提提供了相關的API來處理這些數據而不需要程序員直接操作這些文件或者考慮數據同步的問題。
因為SharedPreferences本身是一個接口,程序無法直接創建SharedPreferences的實例,只能通過Context提供的getSharedPreferences(String name,int mode)方法來獲取SharedPreferences的實例:
public abstract SharedPreferences getSharedPreferences(String name,int mode)
此方法接收兩個參數,第一個參數用於指定SharedPreferences文件的名稱(格式為xml文件),如果指定的文件不存在則會創建一個。SharedPreferences文件都是存放在/data/data/<packagename>/shared_prefs/目錄下的;第二個參數用於指定操作模式:
- MODE_PRIVATE:默認操作模式,和直接傳0效果相同,表示只有當前應用程序才可以對這個SharedPreferences文件進行讀寫
- MODE_WORLD_READABLE:指定此SharedPreferences對其他程序只讀且無法修改。
- MODE_WORLD_WRITEABLE:指定此SharedPreferences能被其他程序讀寫。
- MODE_MULTI_PROCESS:Android2.3之后已經棄之不用了。
得到SharedPreferences對象后,就可以向SharedPreferences文件中存儲數據了,主要分為以下三步:
- 調用SharedPreferences對象的edit()方法來獲取一個SharedPreferences.Editor對象
- 向SharedPreferences.Editor對象中添加數據,比如添加一個布爾型數據就使用putBoolean方法,添加一個字符串就用putString()方法,以此類推
- 調用commit()方法將添加的數據提交,從而完成數據存儲操作
三、實例:保存編輯的短信內容:
通常情況下會發生這樣的問題,我們在編輯短信的同時有電話打進來,那么接電話肯定是要啟動另一個Activiy,那么當前編輯短信的Activity所編輯的信息我們想暫時保存下來,等接完電話后回到該Activity時,可以繼續編輯短信。該功能需要如何去實現呢?
(1)保存數據:
首先使用SharedPreferences這個工具類:
1 private EditText etMsg ; 2 private Button sendButton; 3 private SharedPreferences sp; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 10 etMsg = (EditText)findViewById(R.id.editText1); 11 sendButton = (Button)findViewById(R.id.button1); 12 13 // 獲取共享屬性操作的工具(文件名,操作模式) 14 sp = This.getSharedPreferences("data", 0); 15 }
上方第14行代碼中,調用的方法是:public SharedPreferences getSharedPreferences (String name, int mode)
其中,第一個參數代表XML文件(不要加后綴名),如果有這個文件,就會操作這個文件,如果沒有這個文件,就會創建這個文件;第二個參數代表一種操作模式,0代表私有。
然后,我們要在onPause()方法里保存數據,之所以在onPause()方法里保存,是因為在所有可能會被內存銷毀的生命周期函數中,而onPause()方法最先執行。代碼如下:
//在onPause()方法中保存數據 @Override protected void onPause() { super.onPause(); String msg = etMsg.getText().toString(); Editor editor = sp.edit(); editor.putString("msg", msg); //執行方法:public abstract SharedPreferences.Editor putString (String key, String value) editor.commit(); }
將數據保存在msg變量中,然后拿到Editor這個編輯器,給它put進去。當然,這些只是在內存中操作,如果要反映到文件當中,還要執行commit()方法。
(2)還原數據:
緊接着,我們要在onResume()方法中重新還原數據:(為什么要在這個方法中還原數據,不用我多解釋)
@Override protected void onResume() { super.onResume(); etMsg.setText(sp.getString("msg", "")); }
當程序中第一次啟動的時候,並沒有保存數據,所以返回一個默認的空值。將這個返回的數據放到etMsg控件中就行了。
現在我們運行程序,是可以執行的。
例如,現在編輯內容,然后去別的程序,再回來的時候(就算我們把程序退出了),編輯的內容還依然存在。這個時候,我們打開文件瀏覽器,發現數據是保存在/data/data/<packagename>/shared_prefs/目錄的data.xml文件當中的,而且是永久保存;所以,當在onResume()方法還原數據之后,我們還要加一部分代碼,來刪掉這個文件里的內容(無法刪除文件本身),不然就會永久保存本地成為垃圾了。代碼如下:
protected void onResume() { super.onResume(); etMsg.setText(sp.getString("msg", "")); Editor editor = sp.edit(); editor.clear(); editor.commit(); }
總結之后,最終的完整版代碼如下:
activity_main.xml文件代碼:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="0dp" android:gravity="top" android:layout_weight="1" android:ems="10" /> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Button" /> </LinearLayout>
MainActivity.java的代碼如下:
1 package com.example.smyh001; 2 import android.app.Activity; 3 import android.content.SharedPreferences; 4 import android.content.SharedPreferences.Editor; 5 import android.os.Bundle; 6 import android.view.Menu; 7 import android.widget.Button; 8 import android.widget.EditText; 9 public class MainActivity extends Activity { 10 private EditText etMsg ; 11 private Button sendButton; 12 private SharedPreferences sp; 13 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 19 etMsg = (EditText)findViewById(R.id.editText1); 20 sendButton = (Button)findViewById(R.id.button1); 21 22 // 獲取共享屬性操作的工具 23 sp = getSharedPreferences("data", 0); 24 } 25 //在onPause()方法中保存數據 26 @Override 27 protected void onPause() { 28 super.onPause(); 29 String msg = etMsg.getText().toString(); 30 Editor editor = sp.edit(); 31 editor.putString("msg", msg);//執行方法:public abstract SharedPreferences.Editor putString (String key, String value) 32 editor.commit(); 33 } 34 35 //在onResume()方法中還原數據 36 @Override 37 protected void onResume() { 38 super.onResume(); 39 etMsg.setText(sp.getString("msg", "")); 40 Editor editor = sp.edit(); 41 editor.clear(); 42 editor.commit(); 43 } 44 }
運行程序之后,我們在編輯框輸入一些文字:
退出程序,然后導出data.xml文件,打開后顯示如下:
說明輸入的文本被保存在了data.xml文件當中。當我們再回到程序,之前輸入的文字會被保留在界面上,而data.xml文件中的文本則會被清空。
代碼優化:
上方代碼中如果我們在第40行代碼的后面加下面這一行代碼:
etMsg.setSelection((sp.getString("msg", "")).length());
當返回到原程序時,setSelection方法可將輸入光標移動到文本的末尾位置以便繼續輸入。里面的參數sp.getString("msg", "")是之前所輸入的字符串。
四、實例:實現記住密碼的功能
暫略。
五、PreferenceActivity類的使用:
后面的章節會講到。