欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Android開發(fā)之?dāng)?shù)據(jù)保存技術(shù)(一)

系統(tǒng) 1908 0

Android開發(fā)之?dāng)?shù)據(jù)保存技術(shù)(一)

/*

* Android開發(fā)之?dāng)?shù)據(jù)保存技術(shù)(一)

* 北京Android俱樂部群:167839253

* Created on: 2011-8-17

* Author: blueeagle

* Email: liujiaxiang@gmail.com

*/

本文主要講解Android開發(fā)的數(shù)據(jù)保存技術(shù)。Android的數(shù)據(jù)保存技術(shù)主要有preference,本地文件,SQLite輕量級(jí)數(shù)據(jù)庫,和Content Provider。本文只要講SQLite和Conent Provider。preference和本地文件,將放在后面討論。

SQLite

Android通過SQLite庫提供了完善的關(guān)系數(shù)據(jù)庫功能,而沒有強(qiáng)加任何額外的限制。通過使用SQLite,可以為每一個(gè)應(yīng)用程序創(chuàng)建獨(dú)立的關(guān)系數(shù)據(jù)庫。

所有的Android數(shù)據(jù)庫都存儲(chǔ)在/data/data/<package_name>/databases文件夾下。默認(rèn)條件下,所有的數(shù)據(jù)庫都是私有的,并且只能被創(chuàng)建它們的應(yīng)用程序訪問。要跨應(yīng)用程序共享數(shù)據(jù)庫,可以使用內(nèi)容提供器。

SQLite是一個(gè)關(guān)系數(shù)據(jù)管理系統(tǒng)。它被普遍認(rèn)為是:開源,兼容標(biāo)準(zhǔn),輕量級(jí),Single-tier。

可以用一個(gè)例子來演示SQLite。該例子將記錄存儲(chǔ)在一個(gè)數(shù)據(jù)庫中,然后顯示出來。

新建一個(gè)HelloSQLite的程序。

需要在某個(gè)地方放置該數(shù)據(jù)庫中描述的一些常量,所以要?jiǎng)?chuàng)建一個(gè)Constants接口。

代碼如下:

/*

* Android開發(fā)之?dāng)?shù)據(jù)保存技術(shù)(一)

* Constants.java

* Created on: 2011-8-15

* Author: blueeagle

* Email: liujiaxiang@gmail.com

*/


每個(gè)事件都將作為HeloSQLite表中的一行進(jìn)行存儲(chǔ)。每行都包含一個(gè)_id、time和title列。_id是主鍵,在擴(kuò)展的BaseColums接口中聲明。time和title分別作為時(shí)間和事件標(biāo)記。

使用SQliteOpenHelper。接下來,創(chuàng)建一個(gè)名為SQLiteData的幫助器來表示數(shù)據(jù)庫本身。這個(gè)類擴(kuò)展自Android的SQLiteOpenHelper類,它負(fù)責(zé)管理數(shù)據(jù)庫的創(chuàng)建和版本。需要做的就是提供一個(gè)構(gòu)造方法并且覆寫兩個(gè)方法。

代碼如下:


首次訪問數(shù)據(jù)庫時(shí),SQLiteOpenHelper將注意到該數(shù)據(jù)庫不存在,并調(diào)用onCreate()方法來創(chuàng)建它。

定義Activity主程序。

在HelloSQLite程序中做的第一次嘗試是使用本地的SQLite數(shù)據(jù)庫來存儲(chǔ)事件,并將這些事件顯示為TextView中的一個(gè)字符串。

布局xml文件如下:


這段代碼使用一個(gè)ScrollView,以防太多的時(shí)間沾滿了屏幕。

對(duì)于HelloSQLite.java的實(shí)現(xiàn)如下所示:相關(guān)代碼有注釋說明。


完成上述文件-》運(yùn)行,即可看到結(jié)果顯示出來。這樣就完成了第一個(gè)Android數(shù)據(jù)庫程序。

當(dāng)然,這里面需要注意的問題:

1. 新建數(shù)據(jù)庫的問題

新建數(shù)據(jù)庫的時(shí)候,會(huì)遇到我們用:

db.execSQL("CREATE TABLE "+ TABLE_NAME +"("+ _ID +"INTEGER PRIMARY KEY AUTOINCREMENT,"+ TIME +"INTEGER,"+ TITLE +"TEXT NOT NULL);");

這樣一條語句。有時(shí)候SQL語句書寫錯(cuò)誤,比如少一個(gè)空格就會(huì)引起程序異常退出。這個(gè)時(shí)候建議在db.execSQL()函數(shù)中填寫一個(gè)字符串變量,然后把自己寫的SQL語句賦給字符串變量,在做賦值操作的時(shí)候,先打印出來看看,是不是少空格,多+號(hào)什么的小錯(cuò)誤。

2. 版本號(hào)的問題

關(guān)于構(gòu)造函數(shù)中的版本號(hào),是有明確的說明的。

public MySQLite(Context context, String name, CursorFactory factory,

int version) {

super (context, DATABASE_NAME , factory, DATABASE_VERSION );

這個(gè)版本號(hào)version當(dāng)你有新版本的時(shí)候,則做更新操作,新版本的版本號(hào)將要比老版本高,如果此時(shí)修改版本號(hào),不是向高修改,而是向低修改的話,程序就會(huì)發(fā)生異常了。

3. 數(shù)據(jù)庫文件的問題

對(duì)于onCreate()方法,在程序運(yùn)行的時(shí)候,只運(yùn)行一次,運(yùn)行的這一次就是去創(chuàng)建數(shù)據(jù)庫。將數(shù)據(jù)庫的文件存儲(chǔ)在SD卡中。路徑是data/data/包名/databases里。可以在Eclipse里通過DDMS里的File Explorer來查看。當(dāng)數(shù)據(jù)庫文件存在了以后,則不會(huì)再次運(yùn)行。

完成了上述例子,就算完成了一個(gè)數(shù)據(jù)庫的應(yīng)用。但是如果列表中有數(shù)千個(gè)或者上百萬個(gè)事件。程序?qū)⑦\(yùn)行的非常慢。甚至于耗盡內(nèi)存。解決辦法就是數(shù)據(jù)綁定。

有了數(shù)據(jù)綁定,只需要幾行代碼,就可以將數(shù)據(jù)連接到視圖,從而實(shí)現(xiàn)需求。為了演示,我們修改上面的實(shí)例。

將主程序HelloSQLite.java繼承ListActivity而不是Activity。

將代碼修改為如下所示:


將main.xml修改成如下形式:


增加item.xml為如下:


運(yùn)行結(jié)果如圖所示。

Android開發(fā)之?dāng)?shù)據(jù)保存技術(shù)(一)

當(dāng)然,這只是一個(gè)DEMO,用來展示如何使用SQLite,這個(gè)DEMO存在一些問題。其他應(yīng)用程序都不能向事件數(shù)據(jù)庫添加內(nèi)容,甚至于無法看這些事件。那么針對(duì)這一點(diǎn),引出了Android里的內(nèi)容提供器,即ContentProvider。

內(nèi)容提供器

在Android安全模型中,一個(gè)應(yīng)用程序編寫的文件無法被其他任何應(yīng)用程序所讀寫。每個(gè)應(yīng)用程序都有自己的Linux用戶ID和數(shù)據(jù)目錄,以及其受保護(hù)的內(nèi)存空間。Android程序可以通過下面兩種方式進(jìn)行彼此間的通信。

第一種是IPC(Inter-Process Communication,進(jìn)程間通信):一個(gè)進(jìn)程使用AIDL(Android Interface Definition Language,接口定義語言)和IBinder接口聲明一個(gè)任意的API。調(diào)用該API時(shí),將在進(jìn)程間安全且有效地隊(duì)參數(shù)進(jìn)行編組。這項(xiàng)先進(jìn)技術(shù)用于對(duì)后臺(tái)Service線程進(jìn)行遠(yuǎn)程過程調(diào)用。

第二種就是ContentProvider:進(jìn)程在系統(tǒng)中將他們本身注冊(cè)為某些數(shù)據(jù)類型的提供者。請(qǐng)求該信息時(shí),Android就會(huì)通過一個(gè)固定的API調(diào)用這些進(jìn)程,以它們認(rèn)為合適的方式查詢或者修改內(nèi)容。

ContentProvider管理的任何信息部分都通過一個(gè)URI來尋址,這個(gè)URI類似于以下形式:content://authority/path/id

其中content://是標(biāo)準(zhǔn)要求的前綴。authority是提供者的名稱,建議使用完全限定包名稱,避免出現(xiàn)名稱沖突。Path是提供者內(nèi)部的一個(gè)虛擬目錄,用于標(biāo)識(shí)被請(qǐng)求的數(shù)據(jù)類型。Id是被請(qǐng)求的特定記錄的主鍵,要請(qǐng)求獲得具有特定類型的所有記錄,可以省略此參數(shù)以及后面的斜杠。

Android已經(jīng)內(nèi)置提供了幾個(gè)提供者,包括:

content://browser;

content://contacts;

content://media;

content://settings。

下面我們就來演示如何使用內(nèi)容提供器。

將HelloSQLite程序改為使用內(nèi)容提供器的。對(duì)于HelloSQLite的提供者,下面都是有效的URI:

content://com.blueeagle.HelloSQLite/3 ——表示取id為3的數(shù)據(jù)

content://com.blueeagle.HelloSQLite/ ——表示取所有數(shù)據(jù)

首先需要向Contants.java添加兩個(gè)常量:

public static final String AUTHORITY = "com.blueeagle.HelloSQLite";

public static final Uri CONTENT_URI = Uri. parse ("content://"+ AUTHORITY +"/"+ TABLE_NAME );

接下來可以對(duì)HelloSQLite類做一些修改:

代碼如下:


下面就是實(shí)現(xiàn)ContentProvider

ContentProvider是一個(gè)類似于Activity的高級(jí)對(duì)象,需要向系統(tǒng)進(jìn)行聲明。因此,實(shí)現(xiàn)ContentProvider的第一步是將其添加到AndroidManifest.xml文件中的<activity>標(biāo)簽之前。

其中android:name是類名,android:authorities是在內(nèi)容URI中使用的字符串。接下來創(chuàng)建我們自己的ContentProvider類,為繼承類。ContentProvider創(chuàng)建后就會(huì)被調(diào)用:public boolean onCreate()ContentProvider類中有6個(gè)繼承而來的方法,需要實(shí)現(xiàn):

具體來說需要實(shí)現(xiàn)ContentProvider 類中的6個(gè)抽象方法。
Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):將查詢的數(shù)據(jù)以Cursor 對(duì)象的形式返回。
Uri insert(Uri uri, ContentValues values):向 Content Provider中插入新數(shù)據(jù)記錄,ContentValues 為數(shù)據(jù)記錄的列名和列值映射。
int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):更新Content Provider中已存在的數(shù)據(jù)記錄。

int delete(Uri uri, String selection, String[] selectionArgs):從Content Provider中刪除數(shù)據(jù)記錄。

String getType(Uri uri):返回Content Provider中的數(shù)據(jù)( MIME )類型。

boolean onCreate():當(dāng) Content Provider 啟動(dòng)時(shí)被調(diào)用。

定義一個(gè) URI 類型的靜態(tài)常量,命名為CONTENT_URI。 必須為該常量對(duì)象定義一個(gè)唯一的URI字符串,一般的做法是將 ContentProvider子類的全稱類名作為URI字符串。

定義每個(gè)字段的列名,如果采用的數(shù)據(jù)庫存儲(chǔ)系統(tǒng)為SQLite 數(shù)據(jù)庫,數(shù)據(jù)表列名可以采用數(shù)據(jù)庫中表的列名。不管數(shù)據(jù)表中有沒有其他的唯一標(biāo)識(shí)一個(gè)記錄的字段,都應(yīng)該定義一個(gè)"_id"字段 來唯一標(biāo)識(shí)一個(gè)記錄。模式使用 "INTEGER PRIMARY KEY AUTOINCREMENT" 自動(dòng)更新 一般將這些列名字符串定義為靜態(tài)常量, 如"_id"字段名定義為一個(gè)名為"_ID" 值為 "_id" 的靜態(tài)字符串對(duì)象。

創(chuàng)建好的一個(gè)Content Provider必須在AndroidManifest.xml中聲明。

<provider android:name= ".ItemsProvider"

android:authorities= "com.blueeagle" />

其中name屬性為ContentProvider 子類的全稱類名,authorities 屬性唯一標(biāo)識(shí)了一個(gè)ContentProvider。還可以通過 setReadPermission() 和 setWritePermission() 來設(shè)置其操作權(quán)限。當(dāng)然也可以再上面的 xml中加入 android:readPermission 或者 android: writePermission屬性來控制其權(quán)限。
注意:因?yàn)镃ontentProvider可能被不同的進(jìn)程和線程調(diào)用,所以這些方法必須是線程安全的。

然后需要使用UriMatcher,用于匹配Uri。
用法如下:
首先把需要匹配Uri路徑全部給注冊(cè)上:

對(duì)于Uri:

什么是URI?將其分為A,B,C,D 4個(gè)部分:

A:標(biāo)準(zhǔn)前綴,用來說明一個(gè)Content Provider控制這些數(shù)據(jù),無法改變的;"content://"

B:URI的標(biāo)識(shí),它定義了是哪個(gè)Content Provider提供這些數(shù)據(jù)。對(duì)于第三方應(yīng)用程序,為了保證URI標(biāo)識(shí)的唯一性,它必須是一個(gè)完整的、小寫的 類名。這個(gè)標(biāo)識(shí)在 元素的 authorities屬性中說明:一般是定義該ContentProvider的包.類的名稱 ;"content://hx.android.text.myprovider"

C:路徑,不知道是不是路徑,通俗的講就是你要操作的數(shù)據(jù)庫中表的名字,或者你也可以自己定義,記得在使用的時(shí)候保持一致就ok了;"content://hx.android.text.myprovider/tablename"

D:如果URI中包含表示需要獲取的記錄的ID;則就返回該id對(duì)應(yīng)的數(shù)據(jù),如果沒有ID,就表示返回全部; "content://hx.android.text.myprovider/tablename/#" #表示數(shù)據(jù)id

注冊(cè)完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法對(duì)輸入的Uri進(jìn)行匹配,如果匹配就返回匹配碼,匹配碼是調(diào)用addURI()方法傳入的第三個(gè)參數(shù),例如匹配content://com.blueeagle路徑,返回的匹配碼為1。

//常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼
UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

//添加需要匹配的uri,如果匹配就會(huì)返回匹配碼
//如果match()方法匹配content://com.blueeagle路徑,返回匹配碼為1
sUriMatcher.addURI(“content://com.blueeagle”, “HelloSQLite”, 1);

//如果match()方法匹配content://com.blueeagle/ ***路徑,返回匹配碼為2
//#號(hào)為通配符
sUriMatcher.addURI(“content://com.blueeagle”, “HelloSQLite/#”, 2);

switch(sUriMatcher.match(Uri.parse("content://com.blueeagle /***"))) {
case 1 break;
case 2 break;
default:
//不匹配 break;
}

自定義的contentprovider如下:

ItemsProvider.java


總結(jié)一下,創(chuàng)建一個(gè)新的內(nèi)容提供器。

1.通過擴(kuò)展抽象類ContentProvider可以創(chuàng)建新的內(nèi)容提供器。重寫onCreate方法來打開或者初始化將要使用這個(gè)新的提供器來提供底層數(shù)據(jù)源。

2.還應(yīng)該提供那些用來返回指向這個(gè)提供器的完整的URI的公共靜態(tài)CONTENT_URI變量。提供器之間的內(nèi)容URI應(yīng)該是唯一的,所以最好的做法是使URI路徑以包名為基礎(chǔ)。

定義一個(gè)內(nèi)容提供器URI一般的形式為:

content://com.pakagename/datapath

例如:content://com.blueeagle/items

或者:content://com.blueeagle./items/3

內(nèi)容URI可以表示為這兩種形式中的任意一種形式。前面的一種URI表示對(duì)那種類型中所有的值的請(qǐng)求,后面附加一個(gè)/3的表示對(duì)一條記錄的請(qǐng)求(這里請(qǐng)求的是記錄3)。這兩種形式來訪問提供器都是可行的。

完成這項(xiàng)工作最簡(jiǎn)單的方式是使用一個(gè)UriMatcher。當(dāng)通過內(nèi)容解析器來訪問內(nèi)容提供器的時(shí)候,可以配置UriMathcer來解析URI以確定它們的形式。就像前文說的那樣。

Android開發(fā)之?dāng)?shù)據(jù)保存技術(shù)(一)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 欧美成人免费看片一区 | 日本污网站 | 成人黄色免费 | 成人免费大片黄在线播放 | 日韩av在线中文字幕 | 一级在线观看 | 欧美色性| 亚洲欧美日韩激情在线观看 | 91久久国产口精品久久久久 | 久久中文字幕一区二区三区 | 91精品国产综合久久国产大片 | 午夜影院黄色 | 久久久久久久亚洲视频 | 香蕉国产人午夜视频在线 | 久久久91| 日本污网站 | 欧美激情综合网 | 成人免费黄色 | 天天做天天爱夜夜爽女人爽宅 | 国模无水印一区二区三区 | 色tv国产 | 在线观看毛片视频 | 亚洲视频在线网 | 成人影院欧美大片免费看 | 久久国产成人福利播放 | 欧美精品国产制服第一页 | 亚洲综合国产 | 播播网色播播 | 日本无卡码免费一区二区三区 | 婷婷综合激情网 | 国产一区二区三区在线 | 欧美日韩一区精品 | 91精品网 | 成人免费毛片aaaaaa片 | 锵锵锵锵锵锵锵锵锵好湿好大 | 国产视频一 | 国产男女免费完整版视频 | 91tv最新永久在线地址 | 日韩成人影院 | 久草视频在| 国产在线视频网 |