Hi,大家好!
今天我們主要來講解下,Android的數據共享機制Content Provider。
輕松下:
應 聘
人事總監:您對電腦懂多少?
應聘者A:略懂一二:我用過計算器,戴過電子表,喜歡玩電子游戲機,我還用電視機 和機頂盒上網跟國外的朋友聯系呢......還有,我看過同學用DOS刪除文件......
人事總監:下一位!
人事總監:您對電腦懂多少?
應聘者B:在我頭腦里沒有“電腦”這個詞,只有微型計算機這樣一個概念!一般地 超級掌上型硅單晶片時鍾脈沖輸出計算機(電子表)比較簡單,我小時候常使用它 的編解碼運行程序(鬧鍾功能);至於多功能虛擬現實模擬器(電子游戲機)就復 雜多了,不過我曾經完整測試過多靜態資料單元(只玩過關游戲卡);長大后我開 始對多頻道超高頻無線多媒體接收器(電視機)產生興趣,每天晚上會追蹤特定頻 道的資料;至於傳統的微型計算機,最近我還用調制解調器通過ISP服務商跟國外的 朋友進行多格式多字節實時傳輸(上網聊天),還有,我手下的一個工作伙伴(同學) 經常在我的監控下進行主存儲器與磁化資料存儲器之間的信號轉化或信號取消(用DOS 開機和刪除文件).....
人事總監:ok!明天開始上班。你的配車在地下二層,這是鑰匙......
1 什么是Content Provider?
2 什么是URI?
3 如何使用Content Provider?
1 Android中的Content provider機制可支持在多個應用中存儲和讀取數據。這也是跨應用共享數據的唯一方式。在android系統中,沒有一個公共的內存區域,供多個應用共享存儲數據。
Android提供了一些主要數據類型的Content provider,比如音頻、視頻、圖片和私人通訊錄等。可在android.provider包下面找到一些android提供的Content provider。可以獲得這些Content provider,查詢它們包含的數據,當然前提是已獲得適當的讀取權限。
2 通用資源標志符
(Universal Resource Identifier, 簡稱"URI")。
Uri代表要操作的數據,Android上可用的每種資源 - 圖像、視頻片段等都可以用Uri來表示。
每一個Content Provider都有一個公共URI,這個URI表示Content Provider所提供的數據。
3 使用Content Provider
1 首先,當前應用中,需要有數據庫,上篇博文已經對操作數據庫進行了講解,在這里不再贅述。
2 需要創建一個類並且繼承Content Provider類,並實現這個抽象類中的六個方法。
public int delete(Uri uri, String selection, String[] selectionArgs){}
public String getType(Uri uri) {}
public Uri insert(Uri uri, ContentValues values) {}
public boolean onCreate() {}
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {}public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {}3 需要給當前應用中的Content Provider定義一個URI,並且定義查詢的類型,下邊是一個常量類
package TSD.Jason.DB;
import android.net.Uri;
public class CPFinal {
public final static String DATABASE_NAME="StudentDB"; //數據庫名稱
public final static String TABLE_NAME="StudentInfo"; //數據表名稱
/*定義ContentProvide的名稱,一般以項目包名+CP類名
* 注意:規范CP名稱
* */
public final static String CPNAME = "TSD.Jason.CPDemo.StudentCP";
//定義訪問此CP的路徑 格式: content:// + 路徑 + 子表名稱
public final static Uri CONTENT_URI = Uri.parse("content://" + CPNAME + "/" + TABLE_NAME);
/*定義查詢數據類型
* 如果要查詢所有
* 格式 vnd.android.cursor.dir + 定義的名字
* */
public final static String CONTENT_TYPE="vnd.android.cursor.dir/selectAll";
public final static String CONTENT_TYPE_ITEM ="vnd.android.cursor.item/selectItem";
}4 回到自定義的Content Provider類中,我們需要使用到一個UriMatcher的類,這個類主要是在調用查詢函數query()函數時,會用到。
大家都知道,查詢分為兩大塊,一塊是不帶條件的查詢整表,一塊是帶有一定條件,查詢此條件下的數據。
例如: select * from Table 和 select * from Table where t_id = 1
UriMatcher正是用來規定我們這個Content Provider有哪一些查詢類型和檢查傳入的URI是否符合我們的規定
我們定義了這兩種查詢方式,自然需要將這兩種查詢方式放到UriMatcher中,定義我們查詢的規則
代碼如下
//檢查傳入的uri是否符合我們設置的標准
private final static UriMatcher uriMatcher;
private final static int SELECT_ALL = 1;
private final static int SELECT_ITEM= 2;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(CPFinal.CPNAME, "StudentInfo", SELECT_ALL);
uriMatcher.addURI(CPFinal.CPNAME, "StudentInfo/#", SELECT_ITEM);
}這里可以看到,我們addURI了兩種規則,
一種就是查詢StudentInfo表中的所有數據的,一種是查詢StudentInfo表中ID為什么的數據,#代表表中的ID列當我們需要調用時,需要傳遞的字符串就是 當前定義的ContentProvider的名字,這里我們叫做
public final static String CPNAME = "TSD.Jason.CPDemo.StudentCP";
查詢所有的字符串就是 TSD.Jason.CPDemo.StudentCP/StudentInfo
查詢某條數據的字符串就是 TSD.Jason.CPDemo.StudentCP/StudentInfo/1
檢查URI
需要用到uriMatcher.match(uri)中的match函數
應為我們上邊add了兩個URI規則,並對應兩個int常量,所以如果使用的是
TSD.Jason.CPDemo.StudentCP/StudentInfo 那么match函數返回SELECT_ALL
TSD.Jason.CPDemo.StudentCP/StudentInfo/1 返回SELECT_ITEM
實現下邊的增刪改成函數即可。
package TSD.Jason.CPDemo;
import java.util.HashMap;
import TSD.Jason.DB.CPFinal;
import TSD.Jason.DB.DBColumns;
import TSD.Jason.DB.DBHelp;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
public class StudentCP extends ContentProvider {
//檢查傳入的uri是否符合我們設置的標准
private final static UriMatcher uriMatcher;
private final static int SELECT_ALL = 1;
private final static int SELECT_ITEM= 2;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(CPFinal.CPNAME, "StudentInfo", SELECT_ALL);
uriMatcher.addURI(CPFinal.CPNAME, "StudentInfo/#", SELECT_ITEM);
}
//TSD.Jason.CPTest.StudentCP/StudentInfo
/**
* 需要給數據表中的列,定義一個別名
*/
private static HashMap<String, String> columnName;
static{
columnName = new HashMap<String, String>();
columnName.put(DBColumns.S_NAME, DBColumns.S_NAME);
columnName.put(DBColumns.S_AGE, DBColumns.S_AGE);
columnName.put(DBColumns.S_SEX, DBColumns.S_SEX);
columnName.put(DBColumns.S_ADDRESS, DBColumns.S_ADDRESS);
}
DBHelp dbHelp;
/**
* 根據傳入的URI,返回所傳入的URI所表示的查詢數據類型
* 此函數用來匹配 此類的靜態代碼段中所定義的規則
*/
@Override
public String getType(Uri uri) {
System.out.println(uri.toString()+" -----------gettype");
switch (uriMatcher.match(uri)) {
case SELECT_ALL:
return CPFinal.CONTENT_TYPE;
case SELECT_ITEM:
return CPFinal.CONTENT_TYPE_ITEM;
default:
return null;
}
}
@Override
public boolean onCreate() {
dbHelp = new DBHelp(getContext(), CPFinal.DATABASE_NAME);
System.out.println("create---------------");
return false;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
System.out.println("insert -----------------" + uri.toString());
SQLiteDatabase db = dbHelp.getWritableDatabase();
long result = db.insert(CPFinal.TABLE_NAME, null, values);
System.out.println("insert ------------" + result);
if(result > 0)
{
Uri resultUri = ContentUris.withAppendedId(CPFinal.CONTENT_URI, result);
//通知監聽器,數據已經發生改變
getContext().getContentResolver().notifyChange(resultUri, null);
return resultUri;
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbHelp.getWritableDatabase();
return db.delete(CPFinal.TABLE_NAME, selection, selectionArgs);
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
SQLiteDatabase db = dbHelp.getReadableDatabase();
qb.setTables(CPFinal.TABLE_NAME);
Cursor c = qb.query(db, projection, selection, null, null, null, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}調用
btn1.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
ContentValues contentvalues = new ContentValues();
contentvalues.put(DBColumns.S_NAME, "張三");
contentvalues.put(DBColumns.S_AGE, "23");
contentvalues.put(DBColumns.S_SEX, "男");
contentvalues.put(DBColumns.S_ADDRESS, "北京市海淀區");
Uri uri =getContentResolver().insert(CPFinal.CONTENT_URI, contentvalues);
System.out.println(uri.toString()+"------------activity");
}
});此處調用了增加函數,剩下的刪除、修改、查詢,依次類推。
最后在AndroidManifest.xml中需要注冊provider
<provider android:name=".StudentCP"
android:authorities="TSD.Jason.CPDemo.StudentCP"></provider>