亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Android開發之數據保存技術(一)

系統 1832 0

Android開發之數據保存技術(一)

/*

* Android開發之數據保存技術(一)

* 北京Android俱樂部群:167839253

* Created on: 2011-8-17

* Author: blueeagle

* Email: liujiaxiang@gmail.com

*/

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

SQLite

Android通過SQLite庫提供了完善的關系數據庫功能,而沒有強加任何額外的限制。通過使用SQLite,可以為每一個應用程序創建獨立的關系數據庫。

所有的Android數據庫都存儲在/data/data/<package_name>/databases文件夾下。默認條件下,所有的數據庫都是私有的,并且只能被創建它們的應用程序訪問。要跨應用程序共享數據庫,可以使用內容提供器。

SQLite是一個關系數據管理系統。它被普遍認為是:開源,兼容標準,輕量級,Single-tier。

可以用一個例子來演示SQLite。該例子將記錄存儲在一個數據庫中,然后顯示出來。

新建一個HelloSQLite的程序。

需要在某個地方放置該數據庫中描述的一些常量,所以要創建一個Constants接口。

代碼如下:

/*

* Android開發之數據保存技術(一)

* Constants.java

* Created on: 2011-8-15

* Author: blueeagle

* Email: liujiaxiang@gmail.com

*/


每個事件都將作為HeloSQLite表中的一行進行存儲。每行都包含一個_id、time和title列。_id是主鍵,在擴展的BaseColums接口中聲明。time和title分別作為時間和事件標記。

使用SQliteOpenHelper。接下來,創建一個名為SQLiteData的幫助器來表示數據庫本身。這個類擴展自Android的SQLiteOpenHelper類,它負責管理數據庫的創建和版本。需要做的就是提供一個構造方法并且覆寫兩個方法。

代碼如下:


首次訪問數據庫時,SQLiteOpenHelper將注意到該數據庫不存在,并調用onCreate()方法來創建它。

定義Activity主程序。

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

布局xml文件如下:


這段代碼使用一個ScrollView,以防太多的時間沾滿了屏幕。

對于HelloSQLite.java的實現如下所示:相關代碼有注釋說明。


完成上述文件-》運行,即可看到結果顯示出來。這樣就完成了第一個Android數據庫程序。

當然,這里面需要注意的問題:

1. 新建數據庫的問題

新建數據庫的時候,會遇到我們用:

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

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

2. 版本號的問題

關于構造函數中的版本號,是有明確的說明的。

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

int version) {

super (context, DATABASE_NAME , factory, DATABASE_VERSION );

這個版本號version當你有新版本的時候,則做更新操作,新版本的版本號將要比老版本高,如果此時修改版本號,不是向高修改,而是向低修改的話,程序就會發生異常了。

3. 數據庫文件的問題

對于onCreate()方法,在程序運行的時候,只運行一次,運行的這一次就是去創建數據庫。將數據庫的文件存儲在SD卡中。路徑是data/data/包名/databases里。可以在Eclipse里通過DDMS里的File Explorer來查看。當數據庫文件存在了以后,則不會再次運行。

完成了上述例子,就算完成了一個數據庫的應用。但是如果列表中有數千個或者上百萬個事件。程序將運行的非常慢。甚至于耗盡內存。解決辦法就是數據綁定。

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

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

將代碼修改為如下所示:


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


增加item.xml為如下:


運行結果如圖所示。

Android開發之數據保存技術(一)

當然,這只是一個DEMO,用來展示如何使用SQLite,這個DEMO存在一些問題。其他應用程序都不能向事件數據庫添加內容,甚至于無法看這些事件。那么針對這一點,引出了Android里的內容提供器,即ContentProvider。

內容提供器

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

第一種是IPC(Inter-Process Communication,進程間通信):一個進程使用AIDL(Android Interface Definition Language,接口定義語言)和IBinder接口聲明一個任意的API。調用該API時,將在進程間安全且有效地隊參數進行編組。這項先進技術用于對后臺Service線程進行遠程過程調用。

第二種就是ContentProvider:進程在系統中將他們本身注冊為某些數據類型的提供者。請求該信息時,Android就會通過一個固定的API調用這些進程,以它們認為合適的方式查詢或者修改內容。

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

其中content://是標準要求的前綴。authority是提供者的名稱,建議使用完全限定包名稱,避免出現名稱沖突。Path是提供者內部的一個虛擬目錄,用于標識被請求的數據類型。Id是被請求的特定記錄的主鍵,要請求獲得具有特定類型的所有記錄,可以省略此參數以及后面的斜杠。

Android已經內置提供了幾個提供者,包括:

content://browser;

content://contacts;

content://media;

content://settings。

下面我們就來演示如何使用內容提供器。

將HelloSQLite程序改為使用內容提供器的。對于HelloSQLite的提供者,下面都是有效的URI:

content://com.blueeagle.HelloSQLite/3 ——表示取id為3的數據

content://com.blueeagle.HelloSQLite/ ——表示取所有數據

首先需要向Contants.java添加兩個常量:

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

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

接下來可以對HelloSQLite類做一些修改:

代碼如下:


下面就是實現ContentProvider

ContentProvider是一個類似于Activity的高級對象,需要向系統進行聲明。因此,實現ContentProvider的第一步是將其添加到AndroidManifest.xml文件中的<activity>標簽之前。

其中android:name是類名,android:authorities是在內容URI中使用的字符串。接下來創建我們自己的ContentProvider類,為繼承類。ContentProvider創建后就會被調用:public boolean onCreate()ContentProvider類中有6個繼承而來的方法,需要實現:

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

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

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

boolean onCreate():當 Content Provider 啟動時被調用。

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

定義每個字段的列名,如果采用的數據庫存儲系統為SQLite 數據庫,數據表列名可以采用數據庫中表的列名。不管數據表中有沒有其他的唯一標識一個記錄的字段,都應該定義一個"_id"字段 來唯一標識一個記錄。模式使用 "INTEGER PRIMARY KEY AUTOINCREMENT" 自動更新 一般將這些列名字符串定義為靜態常量, 如"_id"字段名定義為一個名為"_ID" 值為 "_id" 的靜態字符串對象。

創建好的一個Content Provider必須在AndroidManifest.xml中聲明。

<provider android:name= ".ItemsProvider"

android:authorities= "com.blueeagle" />

其中name屬性為ContentProvider 子類的全稱類名,authorities 屬性唯一標識了一個ContentProvider。還可以通過 setReadPermission() 和 setWritePermission() 來設置其操作權限。當然也可以再上面的 xml中加入 android:readPermission 或者 android: writePermission屬性來控制其權限。
注意:因為ContentProvider可能被不同的進程和線程調用,所以這些方法必須是線程安全的。

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

對于Uri:

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

A:標準前綴,用來說明一個Content Provider控制這些數據,無法改變的;"content://"

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

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

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

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

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

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

//如果match()方法匹配content://com.blueeagle/ ***路徑,返回匹配碼為2
//#號為通配符
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


總結一下,創建一個新的內容提供器。

1.通過擴展抽象類ContentProvider可以創建新的內容提供器。重寫onCreate方法來打開或者初始化將要使用這個新的提供器來提供底層數據源。

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

定義一個內容提供器URI一般的形式為:

content://com.pakagename/datapath

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

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

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

完成這項工作最簡單的方式是使用一個UriMatcher。當通過內容解析器來訪問內容提供器的時候,可以配置UriMathcer來解析URI以確定它們的形式。就像前文說的那樣。

Android開發之數據保存技術(一)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 91精品国产99久久 | 国产精品久久久久久久久久一区 | 国内精品一区二区 | 毛片一级视频 | 成人精品视频 | 黄色α片 | 精品视频在线观看 | 久热草| 亚洲 欧美 日韩在线综合福利 | 色啦啦在线观看 | 激情国产白嫩美女在线观看 | 国产欧美亚洲精品第3页在线 | 一本伊在人香蕉线观新在线 | 四虎成人影院网址 | 91资源在线播放 | 在线久操 | 香蕉成人网 | 色哦色哦哦色天天综合 | 亚洲精品一区亚洲精品 | 国产成人久久综合二区 | 亚洲综合狠狠 | 亚洲精品成人在线 | 免费 高清 日本1在线观看 | 手机看片福利盒子久久 | 中文字暮文字暮 | 91亚洲精品福利在线播放 | 97视频久久 | 一区二区高清视频 | 在线欧美v日韩v国产精品v | 视频大全在线观看免费 | 日本免费一级视频 | 婷婷日韩| 不卡在线视频 | 久草精品视频 | 欧美v亚洲v国产v | 午夜免费看| 成人a毛片视频免费看 | 日韩精品中文字幕在线 | 免费在线观看亚洲 | 免费视频网站一级人爱视频 | 久久免费视频2 |