Android学习——数据存储
在Android中,提供了三種數(shù)據(jù)存儲(chǔ)的途徑,和兩種存儲(chǔ)方式。
三種途徑:
l? 系統(tǒng)配置(Shared Preferences):
這類應(yīng)用主要是系統(tǒng)的配置信息的保存,比如我給程序界面設(shè)置了顏色,我想在下一次啟動(dòng)時(shí)還是能夠保留上次設(shè)置的顏色。由于Android系統(tǒng)的界面是采用Activity棧的形式,在系統(tǒng)資源不足時(shí),會(huì)收回一些界面,那么,我想有些操作也是需要在不活動(dòng)時(shí)保留下來(lái)的,等再次激活時(shí)能夠顯示出來(lái)。
l? 文件(Files)
Android是一個(gè)操作系統(tǒng),自然而然對(duì)存儲(chǔ)系統(tǒng)會(huì)有一個(gè)管理,因?yàn)椴捎锰?/span>Linux核心,所有在Andorid系統(tǒng)中,文件也是Linux的形式。當(dāng)然我們的應(yīng)用程序也就可以把數(shù)據(jù)以文件的形式記錄下來(lái)咯。
l? 數(shù)據(jù)庫(kù)(SQLite Databases)
在Andriod系統(tǒng)中,也少不了一個(gè)數(shù)據(jù)庫(kù)管理,但考慮到系統(tǒng)資源(內(nèi)存,硬盤),選擇了輕便型的數(shù)據(jù)庫(kù)SQLite,這是一個(gè)開(kāi)源的關(guān)系型數(shù)據(jù)庫(kù),與普通關(guān)系型數(shù)據(jù)庫(kù)一樣,也具有ACID的特性。
?
兩種存儲(chǔ)方式:
主要是根據(jù)數(shù)據(jù)庫(kù)共享方式來(lái)分
l? 程序內(nèi)自用:
通常我們程序中需要的數(shù)據(jù)一般都是為本程序來(lái)用,所以我們用上面三種途徑來(lái)創(chuàng)建的程序都是默認(rèn)為本程序使用,其他程序無(wú)法獲取操作。
我們ADB插件功能在命令行下輸入:adb shell 來(lái)進(jìn)入手機(jī)的文件系統(tǒng),進(jìn)入CD /data/data目錄。然后ls查看,我們發(fā)現(xiàn),我們?cè)谙到y(tǒng)中安裝的每個(gè)程序在這里都有一個(gè)文件夾,再次進(jìn)入我們的程序后ls查看,會(huì)出現(xiàn)幾個(gè)目錄:shared_prefs、files、databases,這幾個(gè)目錄其實(shí)就是存的我們程序內(nèi)自用的數(shù)據(jù),內(nèi)容分別就是由上面三種途徑創(chuàng)建的,當(dāng)然如果沒(méi)有創(chuàng)建過(guò),這個(gè)目錄可能不存在。
l? 數(shù)據(jù)需要共享:
這類數(shù)據(jù)通常是我們的一些共用數(shù)據(jù),很多程序都會(huì)來(lái)調(diào)用,比如電話薄數(shù)據(jù),就不可能存為私有的了。當(dāng)然,這種方式的話,上面三種途徑中的系統(tǒng)配置就不適用了,“系統(tǒng)配置”只能由本程序訪問(wèn)。也就是說(shuō),只有文件和數(shù)據(jù)庫(kù)可以共享。
?
具體用沒(méi)我們下面依次試一下:
?
(一)系統(tǒng)配置
這類數(shù)據(jù)存儲(chǔ)形式是NVP形式即,name和value的映射map。
存:
// 取得活動(dòng)的preferences對(duì)象.
??? SharedPreferences uiState = getPreferences(0);
// 取得編輯對(duì)象
??? SharedPreferences.Editor editor = uiState.edit();
??? // 添加值
??? editor.putString(KEY, value);
??? editor.putBoolean(KEY, value);
??? editor.commit();//提交保存.
取:
//取得活動(dòng)的preferences對(duì)象.
??? SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
??? // 取得值.
??? String value = settings.getString(KEY, "默認(rèn)值");
Boolean value = settings.getBoolean(KEY, false);
存取時(shí)間:
有了存取的方法后,我們就要想在什么時(shí)候來(lái)存取:
protected void onPause()//系統(tǒng)通知暫停,可以保存設(shè)置
public void onDestroy()//系統(tǒng)通知關(guān)閉,可以保存設(shè)置
public void onCreate(Bundle savedInstanceState) //系統(tǒng)啟動(dòng),可以打開(kāi)設(shè)置
同樣還有其他狀態(tài),我們可以根據(jù)實(shí)際情況來(lái)處理
?
(二)文件操作
l? 打開(kāi)文件并可操作,如果文件不存在會(huì)自動(dòng)創(chuàng)建:
FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
//操作時(shí),在fos里寫入值即可
l? 讀文件:
FileInputStream fis = openFileInput(FILE_NAME);
l? 取得當(dāng)前活動(dòng)創(chuàng)建的文件列表:
String[] lst =fileList()
l? 刪除文件:
super.deleteFile(FILE_NAME);
?
(三)SQLite數(shù)據(jù)庫(kù)操作
數(shù)據(jù)庫(kù)操作無(wú)非是建庫(kù)、建表、增、刪、改、查的一些常用功能。在Android系統(tǒng)中封裝了一個(gè)SQLiteDatabase類,用于這些操作。
l? 建庫(kù)
創(chuàng)建數(shù)據(jù)庫(kù),是由SQLiteOpenHelper類自動(dòng)完成,同時(shí),創(chuàng)建后,會(huì)返回一個(gè)SQLiteDatabase類:
try {
?????? ?????? SQLiteOpenHelper dbHelper= new SQLiteOpenHelper(context,DBName,null,1);
????????????? db = dbHelper.getWritableDatabase();
?????? } catch (SQLiteException ex) {
????????????? db = dbHelper.getReadableDatabase();
?????? }
其中參數(shù)DBName就是數(shù)據(jù)庫(kù)的名稱。getWritableDatabase(),這方法就會(huì)獲取數(shù)據(jù)庫(kù)對(duì)象,如果庫(kù)不存在就會(huì)新建,但這里為什么還要包一層catch呢,主要考慮到,手機(jī)的資源有限,有時(shí)空間不足了,就無(wú)法再寫入數(shù)據(jù),但這里我們可以讀啊,所以在catch中調(diào)用了getReadableDatabase。
?
l? 建表
_db.execSQL(“create table tableName (id integer primary key autoincrement,name text not null);”);
看到,這個(gè)建表其實(shí)跟我們寫的SQL很類似,只是可能一些語(yǔ)法細(xì)節(jié)不同,具體這個(gè)就不寫了,google一下會(huì)N多了。
?
l? 增
當(dāng)然我們可以執(zhí)行一條SQL語(yǔ)句來(lái)插入,我們也可以這樣來(lái):
ContentValues newTaskValues = new ContentValues();
??? // Assign values for each row.
??? newTaskValues.put(KEY_TASK, value);
??? newTaskValues.put(KEY_CREATION_DATE, value);
??? // Insert the row.
db.insert(DATABASE_TABLE, null, newTaskValues);
我們可以將值依次放入一個(gè)Hash表中,然后直接存入。
?
l? 刪
db.delete(tableName, "id=" + _rowIndex, null)
輸入表名,以及條件,當(dāng)然,直接拼成一條標(biāo)準(zhǔn)SQL也是可以的。
?
l? 改
ContentValues newValue = new ContentValues();
??? newValue.put(KEY_TASK, _task);
??? db.update(DATABASE_TABLE, newValue,??? KEY_ID + "=" + _rowIndex, null
?????? 將值存于Hash表中,再直接調(diào)用
?
l? 查
Cursor result =db.query(DATABASE_TABLE,
??????? new String[] { KEY_ID, KEY_TASK, KEY_CREATION_DATE},
??????? null, 條件, null, null, null)
這里,查詢后返回的是一個(gè)游標(biāo),我們可以通過(guò)這游標(biāo)來(lái)獲取數(shù)據(jù),使用方法跟java通用程序一樣。
還有更多的用法,只有邊用邊再搜Google了
?
(四)Content Providers共享數(shù)據(jù)
在前面界面交互中,我們也學(xué)習(xí)到了,Android系統(tǒng)的界面互相調(diào)用時(shí),傳值是采用Uri的方式進(jìn)行的。表面上看,Uri不就是一個(gè)字符串嗎,能傳多少值啊,其實(shí)不然,在Uri中格式:(1)://(2)/(3),這第一段我們不管,這第二段,其實(shí)在系統(tǒng)中是可以定義到我們的Content Providers的,我們可以寫一個(gè)類,比如這個(gè)用來(lái)管理電話薄信息,如:
public class MyProvider extends ContentProvider {
??? private static final String myURI =
?????? "content://com.zjf.MyProvider/items";
public static final Uri CONTENT_URI = Uri.parse(myURI);
…
}
在這里MyProvider繼承了ContentProvider類,然后我們?cè)谙到y(tǒng)中注冊(cè)一下(在manifext.xml中):
<provider android:name=”MyProvider”android:authorities=” com.zjf.MyProvider”/>
然后我們?cè)趥髦禃r(shí)使用:content://com.zjf.MyProvider/1來(lái)通過(guò)這個(gè)Uri我想得到電話薄中第一個(gè)人的信息,我們分析一下,這個(gè)最后一段“1”,就是第一個(gè)記錄咯,“com.zjf.MyProvider”這個(gè)就是標(biāo)記我用哪一套程序來(lái)取數(shù)據(jù),所以說(shuō),我們寫的MyProvider就可以根據(jù)傳入的“1”這個(gè)參數(shù)來(lái)進(jìn)行數(shù)據(jù)的操作,這里你可以保存到文件中,也可以保存到數(shù)據(jù)庫(kù)中,但對(duì)使用者來(lái)說(shuō)是透明的,不需要知道內(nèi)部細(xì)節(jié)。這就是我們說(shuō)的數(shù)據(jù)共享模型。
我們進(jìn)一步看MyProvider繼承處理了哪些類:
@Override
??? public Cursor query(Uri uri, String[] projection, String selection,
??????? String[] selectionArgs, String sortOrder) {
@Override
public int delete(Uri uri, String selection, String[] selectionArgs)
@Override
public Uri insert(Uri uri, ContentValues values)
@Override
??? public int update(Uri uri, ContentValues values, String selection,
??????? String[] selectionArgs)
看到這些大家可能就更家明白了MyProvider就是一個(gè)數(shù)據(jù)的封裝,它按照統(tǒng)一的接口來(lái)提供共享的數(shù)據(jù),每一個(gè)Provider就是處理一類共享數(shù)據(jù)。
當(dāng)然系統(tǒng)中其實(shí)己經(jīng)供了這樣的一些Provider供我們來(lái)使用,比如:Browser記錄了用戶瀏覽記錄;CallLog記錄系統(tǒng)日志;Contacts電話薄;Settings系統(tǒng)設(shè)置等。
看到這個(gè)不知大家有沒(méi)有想到我們前面取得電話薄信息時(shí)是不是用的“content:// Contacts/1”這樣的Uri,對(duì)應(yīng)起來(lái)咯。
?
看了具體的Provider的實(shí)現(xiàn),我們又想到,那這個(gè)統(tǒng)一的數(shù)據(jù)接口標(biāo)準(zhǔn)到底能提供我們哪些功能呢,其實(shí)看了Provider內(nèi)部實(shí)現(xiàn),我們也發(fā)現(xiàn)了,不就也就是增、刪、改、查么。對(duì),我們可能通過(guò)統(tǒng)一的接口來(lái)對(duì)這公用數(shù)據(jù)進(jìn)行這些操作。具體方法如下:
查詢:
Cursor someRows = getContentResolver().query(MyProvider.CONTENT_URI,
null, where, null, order);
插入:
// Create a new row of values to insert.
ContentValues newValues = new ContentValues();
newValues.put(COLUMN_NAME, newValue);
Uri myRowUri = getContentResolver().insert(MyProvider.CONTENT_URI,newValues);
刪除:
getContentResolver().delete(MyProvider.CONTENT_URI, where, null);
修改:
getContentResolver().update(MyProvider.CONTENT_URI, newValues, where,
null);
??????
?????? 這些幾個(gè)功能可以有點(diǎn)難理解,我們看個(gè)應(yīng)用吧:
?????? 我想查詢電話薄中姓陳的人的信息,然后再刪除:
Cursor someRows = getContentResolver().query(“content:// Contacts”,
null, “name like ‘陳%’”, null, order);
//然后從游標(biāo)中獲取數(shù)據(jù)即可。
getContentResolver().delete(“content:// Contacts”, “name like ‘陳%’”, null);//刪除
轉(zhuǎn)載于:https://www.cnblogs.com/zjfstudio/archive/2009/06/01/3764724.html
總結(jié)
以上是生活随笔為你收集整理的Android学习——数据存储的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: eclipse(或者myeclipse)
- 下一篇: SQL Server 20082005维