版權聲明:本文爲博主原創文章,未經博主容許不得轉載。 https://blog.csdn.net/harvic880925/article/details/44591631
前言:如今這段時間沒這麼忙了,要抓緊時間把要總結的知識沉澱下來,今年從新分了項目組,在新項目中應該不會那麼忙了,看來有時間來學一些本身的東西了。如今而言,我須要的是時間。只要不斷的努力,總有一天,你會與從不一樣。加油。html
相關文章:
一、《ContentProvider數據庫共享之——概述》
二、《ContentProvider數據庫共享之——實例講解》
三、《ContentProvider數據庫共享之——MIME類型與getType()》
四、《ContentProvider數據庫共享之——讀寫權限與數據監聽》java
在上篇文章中,已經給你們初步講解了有關ContentProvder的總體流程及設計方式,在這篇文章中將經過實例來說述ContentProvider的操做過程;android
1、ContentProvider提供數據庫查詢接口
在上篇中,咱們提到過,兩個應用間是經過Content URI來媒介傳遞消息的,咱們的應用在收到URI之後,經過匹配完成對應的數據庫操做功能。聽的有點迷糊?不要緊,下面會細講,我這裏要說的是,匹配成功後要完成的數據庫操做!!!那好,咱們的第一步:建數據庫,數據表數據庫
一、利用SQLiteOpenHelper建立數據庫、數據表
在這裏,咱們在一個數據庫(「harvic.db」)中建立兩個數據表」first」與」second」;每一個表都有多出一個字段「table_name」,來保存當前數據表的名稱
代碼以下:數組
-
public class DatabaseHelper extends SQLiteOpenHelper {
-
public static final String DATABASE_NAME = "harvic.db";
-
public static final int DATABASE_VERSION = 1;
-
public static final String TABLE_FIRST_NAME = "first";
-
public static final String TABLE_SECOND_NAME = "second";
-
public static final String SQL_CREATE_TABLE_FIRST = "CREATE TABLE " +TABLE_FIRST_NAME +"("
-
+ BaseColumns._ID +
" INTEGER PRIMARY KEY AUTOINCREMENT,"
-
+
"table_name" +" VARCHAR(50) default 'first',"
-
+
"name" + " VARCHAR(50),"
-
-
-
public static final String SQL_CREATE_TABLE_SECOND = "CREATE TABLE "+TABLE_SECOND_NAME+" ("
-
+ BaseColumns._ID +
" INTEGER PRIMARY KEY AUTOINCREMENT,"
-
+
"table_name" +" VARCHAR(50) default 'second',"
-
+
"name" + " VARCHAR(50),"
-
-
-
-
public DatabaseHelper(Context context) {
-
super(context, DATABASE_NAME, null, DATABASE_VERSION);
-
-
-
-
public void onCreate(SQLiteDatabase db) {
-
Log.e(
"harvic", "create table: " + SQL_CREATE_TABLE_FIRST);
-
db.execSQL(SQL_CREATE_TABLE_FIRST);
-
db.execSQL(SQL_CREATE_TABLE_SECOND);
-
-
-
-
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-
db.execSQL(
"DROP TABLE IF EXISTS first");
-
db.execSQL(
"DROP TABLE IF EXISTS second");
-
-
-
二、利用ContentProvider提供數據庫操做接口
新建一個類PeopleContentProvider,派生自ContentProvider基類,寫好以後,就會自動生成query(),insert(),update(),delete()和getType()方法;這些方法就是根據傳過來的URI來操做數據庫的接口。此時的PeopleContentProvider是這樣的:
-
public class PeopleContentProvider extends ContentProvider {
-
-
public boolean onCreate() {
-
-
-
-
-
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
-
-
-
-
-
public String getType(Uri uri) {
-
-
-
-
-
public Uri insert(Uri uri, ContentValues values) {
-
-
-
-
-
public int delete(Uri uri, String selection, String[] selectionArgs) {
-
-
-
-
-
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-
-
-
三、使用UriMatcher匹配URI
咱們先無論這幾個函數的具體操做,先想一想在上節中我提到的當一個URI逐級匹配到了ContentProvider類裏之後,會怎麼作——利用UriMatcher進行再次匹配!!!UriMatcher匹配成功之後,纔會執行對應的操做。因此上面的那些操做是在UriMatcher匹配以後。
好,咱們就先看看UriMatcher是怎麼匹配的。
-
public class PeopleContentProvider extends ContentProvider {
-
private static final UriMatcher sUriMatcher;
-
private static final int MATCH_FIRST = 1;
-
private static final int MATCH_SECOND = 2;
-
public static final String AUTHORITY = "com.harvic.provider.PeopleContentProvider";
-
public static final Uri CONTENT_URI_FIRST = Uri.parse("content://" + AUTHORITY + "/frist");
-
public static final Uri CONTENT_URI_SECOND = Uri.parse("content://" + AUTHORITY + "/second");
-
-
-
sUriMatcher =
new UriMatcher(UriMatcher.NO_MATCH);
-
sUriMatcher.addURI(AUTHORITY,
"first", MATCH_FIRST);
-
sUriMatcher.addURI(AUTHORITY,
"second", MATCH_SECOND);
-
-
-
private DatabaseHelper mDbHelper;
-
-
-
public boolean onCreate() {
-
mDbHelper =
new DatabaseHelper(getContext());
-
-
-
-
上面的代碼是最重要的一句話:
sUriMatcher.addURI(AUTHORITY, "first", MATCH_FIRST);
addUri的官方聲明爲:
public void addURI (String authority, String path, int code)
- authority:這個參數就是ContentProvider的authority參數,這個參數必須與AndroidManifest.xml中的對應provider的authorities值同樣;
- path:就匹配在URI中authority後的那一坨,在這個例子中,咱們構造了兩個URI
(1)、content://com.harvic.provider.PeopleContentProvider/frist
(2)、content://com.harvic.provider.PeopleContentProvider/second
而path匹配的就是authority後面的/first或者/second
- code:這個值就是在匹配path後,返回的對應的數字匹配值;
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
句話的意思是,若是匹配不成功,返回UriMatcher.NO_MATCH
咱們要作一個應用:外部可使用兩個URI傳來給咱們,當傳來content://com.harvic.provider.PeopleContentProvider/frist時,就操做first數據庫;若是傳來content://com.harvic.provider.PeopleContentProvider/second時,就操做second數據庫
四、insert方法
下面先看看insert方法,主要功能爲:當URI匹配content://com.harvic.provider.PeopleContentProvider/frist時,將數據插入first數據庫
當URI匹配content://com.harvic.provider.PeopleContentProvider/second時,將數據插入second數據庫ide
-
-
public Uri insert(Uri uri, ContentValues values) {
-
SQLiteDatabase db = mDbHelper.getWritableDatabase();
-
switch (sUriMatcher.match(uri)){
-
-
long rowID = db.insert(DatabaseHelper.TABLE_FIRST_NAME, null, values);
-
-
Uri retUri = ContentUris.withAppendedId(CONTENT_URI_FIRST, rowID);
-
-
-
-
-
-
long rowID = db.insert(DatabaseHelper.TABLE_SECOND_NAME, null, values);
-
-
Uri retUri = ContentUris.withAppendedId(CONTENT_URI_SECOND, rowID);
-
-
-
-
-
-
throw new IllegalArgumentException("Unknown URI " + uri);
-
-
-
下面對上面這段代碼進行講解:
首先,利用UriMatcher.match(uri)來匹配到來的URI,若是這個URI與content://com.harvic.provider.PeopleContentProvider/frist匹配,就會返回1即MATCH_FIRST;
即:當與"/first"匹配時,就將數據鍵值對(values)插入到first表中:
long rowID = db.insert(DatabaseHelper.TABLE_FIRST_NAME, null, values);
插入以後,會返回新插入記錄的當前所在行號,而後將行號添加到URI的末尾,作爲結果返回
Uri retUri = ContentUris.withAppendedId(CONTENT_URI_FIRST, rowID);
當匹配content://com.harvic.provider.PeopleContentProvider/second時,同理,再也不贅述。
五、update()方法
在看了insert方法以後,update方法難度也不大,也是根據UriMatcher.match(uri)的返回值來判斷當前與哪一個URI匹配,根據匹配的URI來操做對應的數據庫,代碼以下:函數
-
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-
SQLiteDatabase db = mDbHelper.getWritableDatabase();
-
-
switch(sUriMatcher.match(uri)) {
-
-
count = db.update(DatabaseHelper.TABLE_FIRST_NAME, values, selection, selectionArgs);
-
-
-
count = db.update(DatabaseHelper.TABLE_SECOND_NAME, values, selection, selectionArgs);
-
-
-
-
throw new IllegalArgumentException("Unknow URI : " + uri);
-
-
this.getContext().getContentResolver().notifyChange(uri, null);
-
-
在最後調用getContentResolver().notifyChange(uri, null);來通知當前的數據庫有改變,讓監聽這個數據庫的全部應用執行對應的操做,有關共享數據庫的變量監聽與響應的問題,咱們會在最後一篇中講述。這裏就先不提,這裏不加這一句也是沒問題的。我這裏只是一個引子,你們知道這個事就好了。
六、query() 方法
至於query()方法就再也不細講了,跟上面的同樣,根據不一樣的URI來操做不一樣的查詢操做而已,代碼以下:post
-
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
-
SQLiteQueryBuilder queryBuilder =
new SQLiteQueryBuilder();
-
switch (sUriMatcher.match(uri)) {
-
-
-
queryBuilder.setTables(DatabaseHelper.TABLE_FIRST_NAME);
-
-
-
-
queryBuilder.setTables(DatabaseHelper.TABLE_SECOND_NAME);
-
-
-
-
throw new IllegalArgumentException("Unknow URI: " + uri);
-
-
-
SQLiteDatabase db = mDbHelper.getReadableDatabase();
-
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs,
null, null, null);
-
-
七、delete()方法
delete()方法以下:
-
public int delete(Uri uri, String selection, String[] selectionArgs) {
-
SQLiteDatabase db = mDbHelper.getWritableDatabase();
-
-
switch(sUriMatcher.match(uri)) {
-
-
count = db.delete(DatabaseHelper.TABLE_FIRST_NAME, selection, selectionArgs);
-
-
-
-
count = db.delete(DatabaseHelper.TABLE_SECOND_NAME, selection, selectionArgs);
-
-
-
throw new IllegalArgumentException("Unknow URI :" + uri);
-
-
-
-
八、getType()
這個函數,咱們這裏暫時用不到,直接返回NULL,下篇咱們會專門來說這個函數的做用與意義。
-
public String getType(Uri uri) {
-
-
九、AndroidManifest.xml中聲明provider
在AndroidManifest.xml中要聲明咱們建立的Provider:
-
-
android:authorities=
"com.harvic.provider.PeopleContentProvider"
-
android:name=
".PeopleContentProvider"
-
android:exported=
"true"/>
2、第三方應用經過URI操做共享數據庫
一、ContentResolver操做URI
在第三方應用中,咱們要如何利用URI來執行共享數據數的操做呢,這是利用ContentResolver這個類來完成的。
獲取ContentResolver實例的方法爲:ui
ContentResolver cr = this.getContentResolver();
ContentResolver有下面幾個數據庫操做:查詢、插入、更新、刪除
-
public final Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
-
public final Uri insert (Uri url, ContentValues values)
-
public final int update (Uri uri, ContentValues values, String where, String[] selectionArgs)
-
public final int delete (Uri url, String where, String[] selectionArgs)
第一個參數都是傳入要指定的URI,而後再後面的幾個參數指定數據庫條件——where語句和對應的參數;下面咱們就用戶實例來看看這幾個函數究竟是怎麼用的。
二、全局操做
新建一個工程,命名爲「UseProvider」,界面長這個樣子:this
最上頭有兩個按鈕,用來切換當前使用哪一個URI來增、刪、改、查操做;因爲不一樣的URI會操做不一樣的數據表,因此咱們使用不一樣的URI,會在不一樣的數據表中操做;
先列出來那兩個要匹配的URI,以及全局當前要使用的URI(mCurrentURI ),mCurrentURI 默認是/first對應的URI,若是要切換,使用界面上最上頭的那兩個按鈕來切換當前所使用的URI。
-
public static final String AUTHORITY = "com.harvic.provider.PeopleContentProvider";
-
public static final Uri CONTENT_URI_FIRST = Uri.parse("content://" + AUTHORITY + "/first");
-
public static final Uri CONTENT_URI_SECOND = Uri.parse("content://" + AUTHORITY + "/second");
-
public static Uri mCurrentURI = CONTENT_URI_FIRST;
三、query()——查詢操做
下面先來看看查詢操做的過程:
-
-
Cursor cursor =
this.getContentResolver().query(mCurrentURI, null, null, null, null);
-
Log.e(
"test ", "count=" + cursor.getCount());
-
-
while (!cursor.isAfterLast()) {
-
String table = cursor.getString(cursor.getColumnIndex(
"table_name"));
-
String name = cursor.getString(cursor.getColumnIndex(
"name"));
-
String detail = cursor.getString(cursor.getColumnIndex(
"detail"));
-
Log.e(
"test", "table_name:" + table);
-
Log.e(
"test ", "name: " + name);
-
Log.e(
"test ", "detail: " + detail);
-
-
-
-
其實只有一句話,就完成的查詢操做:(因爲沒有加任何的限定語句,因此是查詢出此數據表中的全部記錄)
Cursor cursor = this.getContentResolver().query(mCurrentURI, null, null, null, null);
而後將返回的數據庫記錄指針Cursor,逐個讀出全部的記錄;
四、insert()插入操做
public final Uri insert (Uri url, ContentValues values)
插入操做有點特殊,第二個函數要求傳入要插入的ContentValues的鍵值對;其實也沒什麼難度,跟普通的數據庫操做同樣;
-
-
ContentValues values =
new ContentValues();
-
values.put(
"name", "hello");
-
values.put(
"detail", "my name is harvic");
-
Uri uri =
this.getContentResolver().insert(mCurrentURI, values);
-
Log.e(
"test ", uri.toString());
-
五、update()更新操做
public final int update (Uri uri, ContentValues values, String where, String[] selectionArgs)
這個函數的意思就是,先用where語句找出要更新的記錄,而後將values鍵值對更新到對應的記錄中;
- uri:即要匹配的URI
- values:這是要更新的鍵值對
- where:SQL中對應的where語句
- selectionArgs:where語句中若是有可變參數,能夠放在selectionArgs這個字符串數組中;這些與數據庫中的用法同樣,再也不細講。
-
-
ContentValues values =
new ContentValues();
-
values.put(
"detail", "my name is harvic !!!!!!!!!!!!!!!!!!!!!!!!!!");
-
int count = this.getContentResolver().update(mCurrentURI, values, "_id = 1", null);
-
Log.e(
"test ", "count=" + count);
-
-
在這裏,咱們將_id = 1的記錄的detail字符更新,在後面多加了N個感嘆號。
六、delete()刪除操做
public final int delete (Uri url, String where, String[] selectionArgs)
刪除操做的參數比較好理解,第二個參數是SQL中的WHERE語句的過濾條件,selectionArgs一樣是Where語句中的可變參數;
-
-
int count = this.getContentResolver().delete(mCurrentURI, "_id = 1", null);
-
Log.e(
"test ", "count=" + count);
-
-
刪除_id = 1的記錄;
3、結果
一、咱們先運行ContentProvider對應的APP:ContentProviderBlog,而後再運行UseProvider;
二、而後先用content://com.harvic.provider.PeopleContentProvider/frist 來操做ContentProviderBlog的數據庫:
三、點兩個insert操做,看返回的URI,在每一個URI後都添加上了當前新插入記錄的行號
四、而後作下查詢操做——query()
因爲咱們的URI是針對first記錄的,因此在這裏的table_name,能夠看到是「first」,即咱們操做的是first表,若是咱們把URI改爲second對應的URI,那操做的就會變成second表
五、更新操做——update()
執行Update()操做,會將_id = 1的記錄的detail字段更新爲「my name is harvic !!!!!!!!!!!!!!!!!!!!!!!!!!」;其它記錄的值不變,結果以下:
六、刪除操做——delete()
一樣,刪除操做也會只刪除_id = 1的記錄,因此操做以後的query()結果以下:
總結:在這篇文章中,咱們寫了兩個應用ContentProviderBlog和UseProvider,其中ContentProviderBlog派生自ContentProvider,提供第三方操做它數據庫的接口;而UseProvider就是所謂第三方應用,在UseProvider中經過URI來操做ContentProviderBlog的數據庫;
好了,到這裏,整個文章就結束了,你們在看完這篇文章之後再回過頭來看第一篇,應該對應用間數據庫共享的總體流程已經有清晰的瞭解了。
源碼來了,源碼包含兩部份內容:
一、《ContentProviderBlog》:這個是提供共享數據庫接口的APP;
二、《UseProvider》:第三方經過URI來操做數據庫的APP;
若是本文有幫到你,記得關注哦
源碼下載地址:http://download.csdn.net/detail/harvic880925/8528507
請你們尊重原創者版權,轉載請標明出處: http://blog.csdn.net/harvic880925/article/details/44591631 謝謝!